blob: 7356408679cbee1d6b4b3402fa0b8148ef627951 [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
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100113/* permit to store configuration section */
114struct cfg_section {
115 struct list list;
116 char *section_name;
117 int (*section_parser)(const char *, int, char **, int);
118};
119
120/* Used to chain configuration sections definitions. This list
121 * stores struct cfg_section
122 */
123struct list sections = LIST_HEAD_INIT(sections);
124
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100126struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100127 const char *name;
128 unsigned int val;
129 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100130 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100131 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100132};
133
134/* proxy->options */
135static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
138 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
139 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
140 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
141 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
142 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100144 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
146 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
147 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
148 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
149 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100150#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100152#else
153 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100154#endif
155
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100157};
158
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159/* proxy->options2 */
160static const struct cfg_opt cfg_opts2[] =
161{
162#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
164 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "splice-request", 0, 0, 0, 0 },
168 { "splice-response", 0, 0, 0, 0 },
169 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
172 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
173 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
174 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
175 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
176 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
177 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
179 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400180 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100181 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200182 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200183 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184 { NULL, 0, 0, 0 }
185};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186
Willy Tarreau6daf3432008-01-22 16:44:08 +0100187static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
189int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100190int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200192/* List head of all known configuration keywords */
193static struct cfg_kw_list cfg_keywords = {
194 .list = LIST_HEAD_INIT(cfg_keywords.list)
195};
196
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197/*
198 * converts <str> to a list of listeners which are dynamically allocated.
199 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
200 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
201 * - <port> is a numerical port from 1 to 65535 ;
202 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
203 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200204 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
205 * not NULL, it must be a valid pointer to either NULL or a freeable area that
206 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200208int 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 +0200209{
210 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 int port, end;
213
214 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100218 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
220 str = next;
221 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100222 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 *next++ = 0;
224 }
225
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100226 ss2 = str2sa_range(str, &port, &end, err,
227 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
228 if (!ss2)
229 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100232 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200233 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100237 if (!port || !end) {
238 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
239 goto fail;
240 }
241
Emeric Bruned760922010-10-22 17:59:25 +0200242 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200244 goto fail;
245 }
246
247 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100252 else if (ss2->ss_family == AF_UNSPEC) {
253 socklen_t addr_len;
254
255 /* We want to attach to an already bound fd whose number
256 * is in the addr part of ss2 when cast to sockaddr_in.
257 * Note that by definition there is a single listener.
258 * We still have to determine the address family to
259 * register the correct protocol.
260 */
261 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
262 addr_len = sizeof(*ss2);
263 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
264 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
265 goto fail;
266 }
267
268 port = end = get_host_port(ss2);
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100271 /* OK the address looks correct */
272 ss = *ss2;
273
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 for (; port <= end; port++) {
275 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100276 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200277 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
278 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
279 l->frontend = curproxy;
280 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau40aa0702013-03-10 23:51:38 +0100282 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200284 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100285 l->state = LI_INIT;
286
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100287 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 tcpv4_add_listener(l);
290 }
Emeric Bruned760922010-10-22 17:59:25 +0200291 else if (ss.ss_family == AF_INET6) {
292 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
293 tcpv6_add_listener(l);
294 }
295 else {
Emeric Bruned760922010-10-22 17:59:25 +0200296 uxst_add_listener(l);
297 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200299 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 } /* end for(port) */
302 } /* end while(next) */
303 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200304 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200305 fail:
306 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200307 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308}
309
Willy Tarreau61d18892009-03-31 10:49:21 +0200310/* Report a warning if a rule is placed after a 'block' rule.
311 * Return 1 if the warning has been emitted, otherwise 0.
312 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100313int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200314{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200315 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200316 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
317 file, line, arg);
318 return 1;
319 }
320 return 0;
321}
322
Willy Tarreau5002f572014-04-23 01:32:02 +0200323/* Report a warning if a rule is placed after an 'http_request' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
326int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
327{
328 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
Willy Tarreau61d18892009-03-31 10:49:21 +0200336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
Willy Tarreauee445d92014-04-23 01:39:04 +0200388/* Report a warning if a rule is placed after a 'use-server' rule.
389 * Return 1 if the warning has been emitted, otherwise 0.
390 */
391int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
392{
393 if (!LIST_ISEMPTY(&proxy->server_rules)) {
394 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
395 file, line, arg);
396 return 1;
397 }
398 return 0;
399}
400
Willy Tarreau61d18892009-03-31 10:49:21 +0200401/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
Willy Tarreau5002f572014-04-23 01:32:02 +0200404 return warnif_rule_after_http_req(proxy, file, line, arg) ||
405 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
406 warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200408 warnif_rule_after_use_backend(proxy, file, line, arg) ||
409 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200410}
411
412/* report a warning if an http-request rule is dangerously placed */
413int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
414{
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
416 warnif_rule_after_reqadd(proxy, file, line, arg) ||
417 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200418 warnif_rule_after_use_backend(proxy, file, line, arg) ||
419 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200420}
421
422/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100423int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200424{
425 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
426 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200427 warnif_rule_after_use_backend(proxy, file, line, arg) ||
428 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200429}
430
431/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100432int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200433{
434 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a redirect rule is dangerously placed */
440int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
443 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200444}
445
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446/* Report it if a request ACL condition uses some keywords that are incompatible
447 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
448 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
449 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100451static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100453 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100455
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100456 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457 return 0;
458
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100459 acl = acl_cond_conflicts(cond, where);
460 if (acl) {
461 if (acl->name && *acl->name)
462 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
463 file, line, acl->name, sample_ckp_names(where));
464 else
465 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 +0200466 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100467 return ERR_WARN;
468 }
469 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100470 return 0;
471
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100472 if (acl->name && *acl->name)
473 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200474 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100475 else
476 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200477 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100478 return ERR_WARN;
479}
480
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200482 * parse a line in a <global> section. Returns the error code, 0 if OK, or
483 * any combination of :
484 * - ERR_ABORT: must abort ASAP
485 * - ERR_FATAL: we can continue parsing but not start the service
486 * - ERR_WARN: a warning has been emitted
487 * - ERR_ALERT: an alert has been emitted
488 * Only the two first ones can stop processing, the two others are just
489 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200491int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492{
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200494 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200495
496 if (!strcmp(args[0], "global")) { /* new section */
497 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200499 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200500 else if (!strcmp(args[0], "ca-base")) {
501#ifdef USE_OPENSSL
502 if (global.ca_base != NULL) {
503 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT;
505 goto out;
506 }
507 if (*(args[1]) == 0) {
508 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
509 err_code |= ERR_ALERT | ERR_FATAL;
510 goto out;
511 }
512 global.ca_base = strdup(args[1]);
513#else
514 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517#endif
518 }
519 else if (!strcmp(args[0], "crt-base")) {
520#ifdef USE_OPENSSL
521 if (global.crt_base != NULL) {
522 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT;
524 goto out;
525 }
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.crt_base = strdup(args[1]);
532#else
533 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536#endif
537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200538 else if (!strcmp(args[0], "daemon")) {
539 global.mode |= MODE_DAEMON;
540 }
541 else if (!strcmp(args[0], "debug")) {
542 global.mode |= MODE_DEBUG;
543 }
544 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100545 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200546 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200547 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100548 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200550 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100551 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100553 else if (!strcmp(args[0], "nosplice")) {
554 global.tune.options &= ~GTUNE_USE_SPLICE;
555 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200556 else if (!strcmp(args[0], "nogetaddrinfo")) {
557 global.tune.options &= ~GTUNE_USE_GAI;
558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559 else if (!strcmp(args[0], "quiet")) {
560 global.mode |= MODE_QUIET;
561 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200562 else if (!strcmp(args[0], "tune.maxpollevents")) {
563 if (global.tune.maxpollevents != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200565 err_code |= ERR_ALERT;
566 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200567 }
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200572 }
573 global.tune.maxpollevents = atol(args[1]);
574 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100575 else if (!strcmp(args[0], "tune.maxaccept")) {
576 if (global.tune.maxaccept != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100585 }
586 global.tune.maxaccept = atol(args[1]);
587 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200588 else if (!strcmp(args[0], "tune.chksize")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.chksize = atol(args[1]);
595 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200596#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100597 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
602 }
603 global.tune.sslcachesize = atol(args[1]);
604 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100605 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
606 unsigned int ssllifetime;
607 const char *res;
608
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
613 }
614
615 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
616 if (res) {
617 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
618 file, linenum, *res, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622
623 global.tune.ssllifetime = ssllifetime;
624 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100625 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.tune.ssl_max_record = atol(args[1]);
632 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200633#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200634 else if (!strcmp(args[0], "tune.bufsize")) {
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.bufsize = atol(args[1]);
641 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
642 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100643 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100644 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200645 }
646 else if (!strcmp(args[0], "tune.maxrewrite")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.maxrewrite = atol(args[1]);
653 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
654 global.tune.maxrewrite = global.tune.bufsize / 2;
655 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100656 else if (!strcmp(args[0], "tune.idletimer")) {
657 unsigned int idle;
658 const char *res;
659
660 if (*(args[1]) == 0) {
661 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT | ERR_FATAL;
663 goto out;
664 }
665
666 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
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 if (idle > 65535) {
675 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.idle_timer = idle;
680 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100681 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
682 if (global.tune.client_rcvbuf != 0) {
683 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT;
685 goto out;
686 }
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.client_rcvbuf = atol(args[1]);
693 }
694 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
695 if (global.tune.server_rcvbuf != 0) {
696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT;
698 goto out;
699 }
700 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.server_rcvbuf = atol(args[1]);
706 }
707 else if (!strcmp(args[0], "tune.sndbuf.client")) {
708 if (global.tune.client_sndbuf != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT;
711 goto out;
712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718 global.tune.client_sndbuf = atol(args[1]);
719 }
720 else if (!strcmp(args[0], "tune.sndbuf.server")) {
721 if (global.tune.server_sndbuf != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT;
724 goto out;
725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.server_sndbuf = atol(args[1]);
732 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200733 else if (!strcmp(args[0], "tune.pipesize")) {
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 global.tune.pipesize = atol(args[1]);
740 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100741 else if (!strcmp(args[0], "tune.http.cookielen")) {
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747 global.tune.cookie_len = atol(args[1]) + 1;
748 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200749 else if (!strcmp(args[0], "tune.http.maxhdr")) {
750 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.max_http_hdr = atol(args[1]);
756 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100757 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
758#ifdef USE_ZLIB
759 if (*args[1]) {
760 global.tune.zlibmemlevel = atoi(args[1]);
761 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
762 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
763 file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 } else {
768 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
769 file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
772 }
773#else
774 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777#endif
778 }
779 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
780#ifdef USE_ZLIB
781 if (*args[1]) {
782 global.tune.zlibwindowsize = atoi(args[1]);
783 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
784 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789 } else {
790 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795#else
796 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799#endif
800 }
William Lallemandf3747832012-11-09 12:33:10 +0100801 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
802 if (*args[1]) {
803 global.tune.comp_maxlevel = atoi(args[1]);
804 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
805 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
806 file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 } else {
811 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
812 file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 else if (!strcmp(args[0], "uid")) {
818 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200819 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 global.uid = atol(args[1]);
829 }
830 else if (!strcmp(args[0], "gid")) {
831 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT;
834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200835 }
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 global.gid = atol(args[1]);
842 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200843 /* user/group name handling */
844 else if (!strcmp(args[0], "user")) {
845 struct passwd *ha_user;
846 if (global.uid != 0) {
847 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT;
849 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200850 }
851 errno = 0;
852 ha_user = getpwnam(args[1]);
853 if (ha_user != NULL) {
854 global.uid = (int)ha_user->pw_uid;
855 }
856 else {
857 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 +0200858 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200859 }
860 }
861 else if (!strcmp(args[0], "group")) {
862 struct group *ha_group;
863 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200864 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200865 err_code |= ERR_ALERT;
866 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200867 }
868 errno = 0;
869 ha_group = getgrnam(args[1]);
870 if (ha_group != NULL) {
871 global.gid = (int)ha_group->gr_gid;
872 }
873 else {
874 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 +0200875 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200876 }
877 }
878 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
885 global.nbproc = atol(args[1]);
886 }
887 else if (!strcmp(args[0], "maxconn")) {
888 if (global.maxconn != 0) {
889 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 global.maxconn = atol(args[1]);
899#ifdef SYSTEM_MAXCONN
900 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
901 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);
902 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905#endif /* SYSTEM_MAXCONN */
906 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200907 else if (!strcmp(args[0], "maxsslconn")) {
908#ifdef USE_OPENSSL
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.maxsslconn = atol(args[1]);
915#else
Emeric Brun0914df82012-10-02 18:45:42 +0200916 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200919#endif
920 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100921 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
922#ifdef USE_OPENSSL
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 free(global.listen_default_ciphers);
929 global.listen_default_ciphers = strdup(args[1]);
930#else
931 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
934#endif
935 }
936 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
937#ifdef USE_OPENSSL
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 free(global.connect_default_ciphers);
944 global.connect_default_ciphers = strdup(args[1]);
945#else
946 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
949#endif
950 }
Emeric Brun850efd52014-01-29 12:24:34 +0100951 else if (!strcmp(args[0], "ssl-server-verify")) {
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957 if (strcmp(args[1],"none") == 0)
958 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
959 else if (strcmp(args[1],"required") == 0)
960 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
961 else {
962 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200967 else if (!strcmp(args[0], "maxconnrate")) {
968 if (global.cps_lim != 0) {
969 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
970 err_code |= ERR_ALERT;
971 goto out;
972 }
973 if (*(args[1]) == 0) {
974 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978 global.cps_lim = atol(args[1]);
979 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200980 else if (!strcmp(args[0], "maxsessrate")) {
981 if (global.sps_lim != 0) {
982 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT;
984 goto out;
985 }
986 if (*(args[1]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
990 }
991 global.sps_lim = atol(args[1]);
992 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200993 else if (!strcmp(args[0], "maxsslrate")) {
994 if (global.ssl_lim != 0) {
995 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT;
997 goto out;
998 }
999 if (*(args[1]) == 0) {
1000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
1003 }
1004 global.ssl_lim = atol(args[1]);
1005 }
William Lallemandd85f9172012-11-09 17:05:39 +01001006 else if (!strcmp(args[0], "maxcomprate")) {
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.comp_rate_lim = atoi(args[1]) * 1024;
1013 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001014 else if (!strcmp(args[0], "maxpipes")) {
1015 if (global.maxpipes != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001024 }
1025 global.maxpipes = atol(args[1]);
1026 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001027 else if (!strcmp(args[0], "maxzlibmem")) {
1028 if (*(args[1]) == 0) {
1029 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1030 err_code |= ERR_ALERT | ERR_FATAL;
1031 goto out;
1032 }
William Lallemande3a7d992012-11-20 11:25:20 +01001033 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001034 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001035 else if (!strcmp(args[0], "maxcompcpuusage")) {
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001042 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001043 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047}
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 else if (!strcmp(args[0], "ulimit-n")) {
1050 if (global.rlimit_nofile != 0) {
1051 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_ALERT;
1053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 }
1055 if (*(args[1]) == 0) {
1056 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
1058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 global.rlimit_nofile = atol(args[1]);
1061 }
1062 else if (!strcmp(args[0], "chroot")) {
1063 if (global.chroot != NULL) {
1064 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001065 err_code |= ERR_ALERT;
1066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 }
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 global.chroot = strdup(args[1]);
1074 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001075 else if (!strcmp(args[0], "description")) {
1076 int i, len=0;
1077 char *d;
1078
1079 if (!*args[1]) {
1080 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1081 file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085
Willy Tarreau348acfe2014-04-14 15:00:39 +02001086 for (i = 1; *args[i]; i++)
1087 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001088
1089 if (global.desc)
1090 free(global.desc);
1091
1092 global.desc = d = (char *)calloc(1, len);
1093
Willy Tarreau348acfe2014-04-14 15:00:39 +02001094 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1095 for (i = 2; *args[i]; i++)
1096 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001097 }
1098 else if (!strcmp(args[0], "node")) {
1099 int i;
1100 char c;
1101
1102 for (i=0; args[1][i]; i++) {
1103 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001104 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1105 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001106 break;
1107 }
1108
1109 if (!i || args[1][i]) {
1110 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1111 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1112 file, linenum, args[0]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116
1117 if (global.node)
1118 free(global.node);
1119
1120 global.node = strdup(args[1]);
1121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 else if (!strcmp(args[0], "pidfile")) {
1123 if (global.pidfile != NULL) {
1124 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 global.pidfile = strdup(args[1]);
1134 }
Emeric Bruned760922010-10-22 17:59:25 +02001135 else if (!strcmp(args[0], "unix-bind")) {
1136 int cur_arg = 1;
1137 while (*(args[cur_arg])) {
1138 if (!strcmp(args[cur_arg], "prefix")) {
1139 if (global.unix_bind.prefix != NULL) {
1140 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1141 err_code |= ERR_ALERT;
1142 cur_arg += 2;
1143 continue;
1144 }
1145
1146 if (*(args[cur_arg+1]) == 0) {
1147 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
1150 }
1151 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1152 cur_arg += 2;
1153 continue;
1154 }
1155
1156 if (!strcmp(args[cur_arg], "mode")) {
1157
1158 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1159 cur_arg += 2;
1160 continue;
1161 }
1162
1163 if (!strcmp(args[cur_arg], "uid")) {
1164
1165 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1166 cur_arg += 2;
1167 continue;
1168 }
1169
1170 if (!strcmp(args[cur_arg], "gid")) {
1171
1172 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1173 cur_arg += 2;
1174 continue;
1175 }
1176
1177 if (!strcmp(args[cur_arg], "user")) {
1178 struct passwd *user;
1179
1180 user = getpwnam(args[cur_arg + 1]);
1181 if (!user) {
1182 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1183 file, linenum, args[0], args[cur_arg + 1 ]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 global.unix_bind.ux.uid = user->pw_uid;
1189 cur_arg += 2;
1190 continue;
1191 }
1192
1193 if (!strcmp(args[cur_arg], "group")) {
1194 struct group *group;
1195
1196 group = getgrnam(args[cur_arg + 1]);
1197 if (!group) {
1198 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1199 file, linenum, args[0], args[cur_arg + 1 ]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203
1204 global.unix_bind.ux.gid = group->gr_gid;
1205 cur_arg += 2;
1206 continue;
1207 }
1208
Willy Tarreaub48f9582011-09-05 01:17:06 +02001209 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214 }
William Lallemand0f99e342011-10-12 17:50:54 +02001215 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1216 /* delete previous herited or defined syslog servers */
1217 struct logsrv *back;
1218 struct logsrv *tmp;
1219
1220 if (*(args[1]) != 0) {
1221 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto out;
1224 }
1225
1226 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1227 LIST_DEL(&tmp->list);
1228 free(tmp);
1229 }
1230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001232 struct sockaddr_storage *sk;
1233 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001234 struct logsrv *logsrv;
1235
Willy Tarreaubaaee002006-06-26 02:48:02 +02001236 if (*(args[1]) == 0 || *(args[2]) == 0) {
1237 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 }
William Lallemand0f99e342011-10-12 17:50:54 +02001241
1242 logsrv = calloc(1, sizeof(struct logsrv));
1243
1244 logsrv->facility = get_log_facility(args[2]);
1245 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001246 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001247 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001248 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001249 }
1250
William Lallemand0f99e342011-10-12 17:50:54 +02001251 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001253 logsrv->level = get_log_level(args[3]);
1254 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001255 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001256 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001257 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258 }
1259 }
1260
William Lallemand0f99e342011-10-12 17:50:54 +02001261 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001262 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001263 logsrv->minlvl = get_log_level(args[4]);
1264 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001265 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001266 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001267 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001268 }
1269 }
1270
Willy Tarreau902636f2013-03-10 19:44:48 +01001271 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001272 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001273 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001274 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001275 free(logsrv);
1276 goto out;
1277 }
1278 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001279
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001280 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001281 if (port1 != port2) {
1282 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1283 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001284 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001285 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001286 goto out;
1287 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001288
William Lallemand0f99e342011-10-12 17:50:54 +02001289 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001290 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001291 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001293
William Lallemand0f99e342011-10-12 17:50:54 +02001294 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001295 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001296 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1297 char *name;
1298 int len;
1299
1300 if (global.log_send_hostname != NULL) {
1301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT;
1303 goto out;
1304 }
1305
1306 if (*(args[1]))
1307 name = args[1];
1308 else
1309 name = hostname;
1310
1311 len = strlen(name);
1312
1313 /* We'll add a space after the name to respect the log format */
1314 free(global.log_send_hostname);
1315 global.log_send_hostname = malloc(len + 2);
1316 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1317 }
Kevinm48936af2010-12-22 16:08:21 +00001318 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 free(global.log_tag);
1325 global.log_tag = strdup(args[1]);
1326 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001327 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1328 if (global.spread_checks != 0) {
1329 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001330 err_code |= ERR_ALERT;
1331 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001332 }
1333 if (*(args[1]) == 0) {
1334 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001337 }
1338 global.spread_checks = atol(args[1]);
1339 if (global.spread_checks < 0 || global.spread_checks > 50) {
1340 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001344 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1345 const char *err;
1346 unsigned int val;
1347
1348
1349 if (*(args[1]) == 0) {
1350 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto out;
1353 }
1354
1355 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1356 if (err) {
1357 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1358 err_code |= ERR_ALERT | ERR_FATAL;
1359 }
1360 global.max_spread_checks = val;
1361 if (global.max_spread_checks < 0) {
1362 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 }
1365 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001366 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1367#ifdef USE_CPU_AFFINITY
1368 int cur_arg, i;
1369 unsigned int proc = 0;
1370 unsigned long cpus = 0;
1371
1372 if (strcmp(args[1], "all") == 0)
1373 proc = 0xFFFFFFFF;
1374 else if (strcmp(args[1], "odd") == 0)
1375 proc = 0x55555555;
1376 else if (strcmp(args[1], "even") == 0)
1377 proc = 0xAAAAAAAA;
1378 else {
1379 proc = atoi(args[1]);
1380 if (proc >= 1 && proc <= 32)
1381 proc = 1 << (proc - 1);
1382 }
1383
1384 if (!proc || !*args[2]) {
1385 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1386 file, linenum, args[0]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390
1391 cur_arg = 2;
1392 while (*args[cur_arg]) {
1393 unsigned int low, high;
1394
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001395 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001396 char *dash = strchr(args[cur_arg], '-');
1397
1398 low = high = str2uic(args[cur_arg]);
1399 if (dash)
1400 high = str2uic(dash + 1);
1401
1402 if (high < low) {
1403 unsigned int swap = low;
1404 low = high;
1405 high = swap;
1406 }
1407
1408 if (low < 0 || high >= sizeof(long) * 8) {
1409 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1410 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
1415 while (low <= high)
1416 cpus |= 1UL << low++;
1417 }
1418 else {
1419 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1420 file, linenum, args[0], args[cur_arg]);
1421 err_code |= ERR_ALERT | ERR_FATAL;
1422 goto out;
1423 }
1424 cur_arg++;
1425 }
1426 for (i = 0; i < 32; i++)
1427 if (proc & (1 << i))
1428 global.cpu_map[i] = cpus;
1429#else
1430 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1431 err_code |= ERR_ALERT | ERR_FATAL;
1432 goto out;
1433#endif
1434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001436 struct cfg_kw_list *kwl;
1437 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001438 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001439
1440 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1441 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1442 if (kwl->kw[index].section != CFG_GLOBAL)
1443 continue;
1444 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001445 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001446 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001447 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001449 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001450 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001451 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_WARN;
1453 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001454 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001456 }
1457 }
1458 }
1459
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001463
Willy Tarreau058e9072009-07-20 09:30:05 +02001464 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001465 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467}
1468
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001469void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001471 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 defproxy.mode = PR_MODE_TCP;
1473 defproxy.state = PR_STNEW;
1474 defproxy.maxconn = cfg_maxpconn;
1475 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001476
Simon Horman66183002013-02-23 10:16:43 +09001477 defproxy.defsrv.check.inter = DEF_CHKINTR;
1478 defproxy.defsrv.check.fastinter = 0;
1479 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001480 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1481 defproxy.defsrv.agent.fastinter = 0;
1482 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001483 defproxy.defsrv.check.rise = DEF_RISETIME;
1484 defproxy.defsrv.check.fall = DEF_FALLTIME;
1485 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1486 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001487 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001488 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001489 defproxy.defsrv.maxqueue = 0;
1490 defproxy.defsrv.minconn = 0;
1491 defproxy.defsrv.maxconn = 0;
1492 defproxy.defsrv.slowstart = 0;
1493 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1494 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1495 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496}
1497
Willy Tarreauade5ec42010-01-28 19:33:49 +01001498
1499static int create_cond_regex_rule(const char *file, int line,
1500 struct proxy *px, int dir, int action, int flags,
1501 const char *cmd, const char *reg, const char *repl,
1502 const char **cond_start)
1503{
1504 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001505 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001506 const char *err;
1507 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001508 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001509
1510 if (px == &defproxy) {
1511 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto err;
1514 }
1515
1516 if (*reg == 0) {
1517 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto err;
1520 }
1521
1522 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1523 err_code |= ERR_WARN;
1524
Willy Tarreau5321c422010-01-28 20:35:13 +01001525 if (cond_start &&
1526 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001527 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1528 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1529 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto err;
1532 }
1533 }
1534 else if (cond_start && **cond_start) {
1535 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1536 file, line, cmd, *cond_start);
1537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto err;
1539 }
1540
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001541 err_code |= warnif_cond_conflicts(cond,
1542 (dir == SMP_OPT_DIR_REQ) ?
1543 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1544 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1545 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001546
Willy Tarreauade5ec42010-01-28 19:33:49 +01001547 preg = calloc(1, sizeof(regex_t));
1548 if (!preg) {
1549 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1550 err_code = ERR_ALERT | ERR_FATAL;
1551 goto err;
1552 }
1553
1554 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1555 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1556 err_code = ERR_ALERT | ERR_FATAL;
1557 goto err;
1558 }
1559
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001560 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001561 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001562 if (repl && err) {
1563 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1564 file, line, cmd, *err);
1565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto err;
1567 }
1568
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001569 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001570 err_code |= ERR_WARN;
1571
Willy Tarreauf4068b62012-05-08 17:37:49 +02001572 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001573 return err_code;
1574 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001575 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001576 free(preg);
1577 return err_code;
1578}
1579
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001581 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001582 * Returns the error code, 0 if OK, or any combination of :
1583 * - ERR_ABORT: must abort ASAP
1584 * - ERR_FATAL: we can continue parsing but not start the service
1585 * - ERR_WARN: a warning has been emitted
1586 * - ERR_ALERT: an alert has been emitted
1587 * Only the two first ones can stop processing, the two others are just
1588 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001590int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1591{
1592 static struct peers *curpeers = NULL;
1593 struct peer *newpeer = NULL;
1594 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001595 struct bind_conf *bind_conf;
1596 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001597 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001598 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001599
1600 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001601 if (!*args[1]) {
1602 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001603 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001604 goto out;
1605 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001606
1607 err = invalid_char(args[1]);
1608 if (err) {
1609 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1610 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001611 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001612 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001613 }
1614
1615 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1616 /*
1617 * If there are two proxies with the same name only following
1618 * combinations are allowed:
1619 */
1620 if (strcmp(curpeers->id, args[1]) == 0) {
1621 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1622 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1623 err_code |= ERR_WARN;
1624 }
1625 }
1626
1627 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1628 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1629 err_code |= ERR_ALERT | ERR_ABORT;
1630 goto out;
1631 }
1632
1633 curpeers->next = peers;
1634 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001635 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001636 curpeers->conf.line = linenum;
1637 curpeers->last_change = now.tv_sec;
1638 curpeers->id = strdup(args[1]);
1639 }
1640 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001641 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001643 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001644
1645 if (!*args[2]) {
1646 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1647 file, linenum, args[0]);
1648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
1650 }
1651
1652 err = invalid_char(args[1]);
1653 if (err) {
1654 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1655 file, linenum, *err, args[1]);
1656 err_code |= ERR_ALERT | ERR_FATAL;
1657 goto out;
1658 }
1659
1660 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
1664 }
1665
1666 /* the peers are linked backwards first */
1667 curpeers->count++;
1668 newpeer->next = curpeers->remote;
1669 curpeers->remote = newpeer;
1670 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001671 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 newpeer->conf.line = linenum;
1673
1674 newpeer->last_change = now.tv_sec;
1675 newpeer->id = strdup(args[1]);
1676
Willy Tarreau902636f2013-03-10 19:44:48 +01001677 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001678 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001679 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001682 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001683
1684 proto = protocol_by_family(sk->ss_family);
1685 if (!proto || !proto->connect) {
1686 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1687 file, linenum, args[0], args[1]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001691
1692 if (port1 != port2) {
1693 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1694 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001695 err_code |= ERR_ALERT | ERR_FATAL;
1696 goto out;
1697 }
1698
Willy Tarreau2aa38802013-02-20 19:20:59 +01001699 if (!port1) {
1700 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1701 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
1704 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001705
Emeric Brun32da3c42010-09-23 18:39:19 +02001706 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001707 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001708 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001709 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001710
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 if (strcmp(newpeer->id, localpeer) == 0) {
1712 /* Current is local peer, it define a frontend */
1713 newpeer->local = 1;
1714
1715 if (!curpeers->peers_fe) {
1716 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1717 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1718 err_code |= ERR_ALERT | ERR_ABORT;
1719 goto out;
1720 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001721
Willy Tarreau237250c2011-07-29 01:49:03 +02001722 init_new_proxy(curpeers->peers_fe);
1723 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001724
1725 curpeers->peers_fe->last_change = now.tv_sec;
1726 curpeers->peers_fe->id = strdup(args[1]);
1727 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001728 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001729 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1730 curpeers->peers_fe->timeout.connect = 5000;
1731 curpeers->peers_fe->accept = peer_accept;
1732 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001733 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1734 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001735
1736 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1737
Willy Tarreau902636f2013-03-10 19:44:48 +01001738 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1739 if (errmsg && *errmsg) {
1740 indent_msg(&errmsg, 2);
1741 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001742 }
1743 else
1744 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1745 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001746 err_code |= ERR_FATAL;
1747 goto out;
1748 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001749
1750 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1751 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1752 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1753 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1754 l->accept = session_accept;
1755 l->handler = process_session;
1756 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1757 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1758 global.maxsock += l->maxconn;
1759 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001760 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001761 else {
1762 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1763 file, linenum, args[0], args[1],
1764 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1765 err_code |= ERR_FATAL;
1766 goto out;
1767 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001768 }
1769 } /* neither "peer" nor "peers" */
1770 else if (*args[0] != 0) {
1771 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775
1776out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001777 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001778 return err_code;
1779}
1780
Willy Tarreau3842f002009-06-14 11:39:52 +02001781int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782{
1783 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001784 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001785 int rc;
1786 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001787 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001788 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001789 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001790 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001791 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792
Willy Tarreau977b8e42006-12-29 14:19:17 +01001793 if (!strcmp(args[0], "listen"))
1794 rc = PR_CAP_LISTEN;
1795 else if (!strcmp(args[0], "frontend"))
1796 rc = PR_CAP_FE | PR_CAP_RS;
1797 else if (!strcmp(args[0], "backend"))
1798 rc = PR_CAP_BE | PR_CAP_RS;
1799 else if (!strcmp(args[0], "ruleset"))
1800 rc = PR_CAP_RS;
1801 else
1802 rc = PR_CAP_NONE;
1803
1804 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001805 struct ebpt_node *node;
1806
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 if (!*args[1]) {
1808 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1809 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1810 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_ALERT | ERR_ABORT;
1812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001814
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001815 err = invalid_char(args[1]);
1816 if (err) {
1817 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1818 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001820 }
1821
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001822 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1823 curproxy = container_of(node, struct proxy, conf.by_name);
1824
1825 if (strcmp(curproxy->id, args[1]) != 0)
1826 break;
1827
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001828 /*
1829 * If there are two proxies with the same name only following
1830 * combinations are allowed:
1831 *
1832 * listen backend frontend ruleset
1833 * listen - - - -
1834 * backend - - OK -
1835 * frontend - OK - -
1836 * ruleset - - - -
1837 */
1838
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001839 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1840 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001841 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1842 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1843 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001845 }
1846 }
1847
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1849 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001850 err_code |= ERR_ALERT | ERR_ABORT;
1851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001853
Willy Tarreau97cb7802010-01-03 20:23:58 +01001854 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001855 curproxy->next = proxy;
1856 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001857 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1858 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001859 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001862 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863
1864 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001866 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001867
Willy Tarreau4348fad2012-09-20 16:48:07 +02001868 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1869
Willy Tarreau902636f2013-03-10 19:44:48 +01001870 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1871 if (errmsg && *errmsg) {
1872 indent_msg(&errmsg, 2);
1873 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001874 }
1875 else
1876 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1877 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_FATAL;
1879 goto out;
1880 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001881
Willy Tarreau4348fad2012-09-20 16:48:07 +02001882 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001883 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 }
1886
1887 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001888 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001889 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001890
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001893 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001894 curproxy->no_options = defproxy.no_options;
1895 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001896 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001897 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001898 curproxy->except_net = defproxy.except_net;
1899 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001900 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001901 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001903 if (defproxy.fwdfor_hdr_len) {
1904 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1905 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1906 }
1907
Willy Tarreaub86db342009-11-30 11:50:16 +01001908 if (defproxy.orgto_hdr_len) {
1909 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1910 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1911 }
1912
Mark Lamourinec2247f02012-01-04 13:02:01 -05001913 if (defproxy.server_id_hdr_len) {
1914 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1915 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1916 }
1917
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (curproxy->cap & PR_CAP_FE) {
1919 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001920 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001921 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
1923 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001924 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1925 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926
1927 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929
Willy Tarreau977b8e42006-12-29 14:19:17 +01001930 if (curproxy->cap & PR_CAP_BE) {
1931 curproxy->fullconn = defproxy.fullconn;
1932 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02001933 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001935 if (defproxy.check_req) {
1936 curproxy->check_req = calloc(1, defproxy.check_len);
1937 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1938 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001939 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001941 if (defproxy.expect_str) {
1942 curproxy->expect_str = strdup(defproxy.expect_str);
1943 if (defproxy.expect_regex) {
1944 /* note: this regex is known to be valid */
1945 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1946 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1947 }
1948 }
1949
Willy Tarreau67402132012-05-31 20:40:20 +02001950 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (defproxy.cookie_name)
1952 curproxy->cookie_name = strdup(defproxy.cookie_name);
1953 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001954 if (defproxy.cookie_domain)
1955 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001956
Willy Tarreau31936852010-10-06 16:59:56 +02001957 if (defproxy.cookie_maxidle)
1958 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1959
1960 if (defproxy.cookie_maxlife)
1961 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1962
Emeric Brun647caf12009-06-30 17:57:00 +02001963 if (defproxy.rdp_cookie_name)
1964 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1965 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1966
Willy Tarreau01732802007-11-01 22:48:15 +01001967 if (defproxy.url_param_name)
1968 curproxy->url_param_name = strdup(defproxy.url_param_name);
1969 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001970
Benoitaffb4812009-03-25 13:02:10 +01001971 if (defproxy.hh_name)
1972 curproxy->hh_name = strdup(defproxy.hh_name);
1973 curproxy->hh_len = defproxy.hh_len;
1974 curproxy->hh_match_domain = defproxy.hh_match_domain;
1975
Willy Tarreauef9a3602012-12-08 22:29:20 +01001976 if (defproxy.conn_src.iface_name)
1977 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1978 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001979 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001980#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001981 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001982#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001985 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (defproxy.capture_name)
1987 curproxy->capture_name = strdup(defproxy.capture_name);
1988 curproxy->capture_namelen = defproxy.capture_namelen;
1989 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
Willy Tarreau977b8e42006-12-29 14:19:17 +01001992 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001993 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001994 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001995 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001996 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 curproxy->mon_net = defproxy.mon_net;
1998 curproxy->mon_mask = defproxy.mon_mask;
1999 if (defproxy.monitor_uri)
2000 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2001 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002002 if (defproxy.defbe.name)
2003 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002004
2005 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002006 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2007 if (curproxy->conf.logformat_string &&
2008 curproxy->conf.logformat_string != default_http_log_format &&
2009 curproxy->conf.logformat_string != default_tcp_log_format &&
2010 curproxy->conf.logformat_string != clf_http_log_format)
2011 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2012
2013 if (defproxy.conf.lfs_file) {
2014 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2015 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2016 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002017 }
2018
2019 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002020 curproxy->timeout.connect = defproxy.timeout.connect;
2021 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002022 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002023 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002024 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002025 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002026 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002027 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002028 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002029 }
2030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002032 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002033
2034 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002035 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002036 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002037 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002038 LIST_INIT(&node->list);
2039 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2040 }
2041
Willy Tarreau62a61232013-04-12 18:13:46 +02002042 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2043 if (curproxy->conf.uniqueid_format_string)
2044 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2045
2046 if (defproxy.conf.uif_file) {
2047 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2048 curproxy->conf.uif_line = defproxy.conf.uif_line;
2049 }
William Lallemanda73203e2012-03-12 12:48:57 +01002050
2051 /* copy default header unique id */
2052 if (defproxy.header_unique_id)
2053 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2054
William Lallemand82fe75c2012-10-23 10:25:10 +02002055 /* default compression options */
2056 if (defproxy.comp != NULL) {
2057 curproxy->comp = calloc(1, sizeof(struct comp));
2058 curproxy->comp->algos = defproxy.comp->algos;
2059 curproxy->comp->types = defproxy.comp->types;
2060 }
2061
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002063 curproxy->conf.used_listener_id = EB_ROOT;
2064 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002065
Willy Tarreau93893792009-07-23 13:19:11 +02002066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 }
2068 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2069 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002070 /* FIXME-20070101: we should do this too at the end of the
2071 * config parsing to free all default values.
2072 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073 free(defproxy.check_req);
2074 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002075 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002076 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002077 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002078 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002079 free(defproxy.capture_name);
2080 free(defproxy.monitor_uri);
2081 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002082 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002083 free(defproxy.fwdfor_hdr_name);
2084 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002085 free(defproxy.orgto_hdr_name);
2086 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002087 free(defproxy.server_id_hdr_name);
2088 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002089 free(defproxy.expect_str);
2090 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002091
Willy Tarreau62a61232013-04-12 18:13:46 +02002092 if (defproxy.conf.logformat_string != default_http_log_format &&
2093 defproxy.conf.logformat_string != default_tcp_log_format &&
2094 defproxy.conf.logformat_string != clf_http_log_format)
2095 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002096
Willy Tarreau62a61232013-04-12 18:13:46 +02002097 free(defproxy.conf.uniqueid_format_string);
2098 free(defproxy.conf.lfs_file);
2099 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002100
Willy Tarreaua534fea2008-08-03 12:19:50 +02002101 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002102 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 /* we cannot free uri_auth because it might already be used */
2105 init_default_instance();
2106 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002107 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2108 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
2112 else if (curproxy == NULL) {
2113 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002117
2118 /* update the current file and line being parsed */
2119 curproxy->conf.args.file = curproxy->conf.file;
2120 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121
2122 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002123 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2124 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2125 if (err_code & ERR_FATAL)
2126 goto out;
2127 }
2128 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002129 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002130 int cur_arg;
2131
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 if (curproxy == &defproxy) {
2133 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002138 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139
Willy Tarreau24709282013-03-10 21:32:12 +01002140 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002141 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002146
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002147 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002148
2149 /* use default settings for unix sockets */
2150 bind_conf->ux.uid = global.unix_bind.ux.uid;
2151 bind_conf->ux.gid = global.unix_bind.ux.gid;
2152 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002153
2154 /* NOTE: the following line might create several listeners if there
2155 * are comma-separated IPs or port ranges. So all further processing
2156 * will have to be applied to all listeners created after last_listen.
2157 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002158 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2159 if (errmsg && *errmsg) {
2160 indent_msg(&errmsg, 2);
2161 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002162 }
2163 else
2164 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2165 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002169
Willy Tarreau4348fad2012-09-20 16:48:07 +02002170 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2171 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002172 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002173 }
2174
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002175 cur_arg = 2;
2176 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002177 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002178 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002179 char *err;
2180
Willy Tarreau26982662012-09-12 23:17:10 +02002181 kw = bind_find_kw(args[cur_arg]);
2182 if (kw) {
2183 char *err = NULL;
2184 int code;
2185
2186 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002187 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2188 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002189 cur_arg += 1 + kw->skip ;
2190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
2192 }
2193
Willy Tarreau4348fad2012-09-20 16:48:07 +02002194 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002195 err_code |= code;
2196
2197 if (code) {
2198 if (err && *err) {
2199 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002200 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002201 }
2202 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002203 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2204 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002205 if (code & ERR_FATAL) {
2206 free(err);
2207 cur_arg += 1 + kw->skip;
2208 goto out;
2209 }
2210 }
2211 free(err);
2212 cur_arg += 1 + kw->skip;
2213 continue;
2214 }
2215
Willy Tarreau8638f482012-09-18 18:01:17 +02002216 err = NULL;
2217 if (!bind_dumped) {
2218 bind_dump_kws(&err);
2219 indent_msg(&err, 4);
2220 bind_dumped = 1;
2221 }
2222
2223 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2224 file, linenum, args[0], args[1], args[cur_arg],
2225 err ? " Registered keywords :" : "", err ? err : "");
2226 free(err);
2227
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002230 }
Willy Tarreau93893792009-07-23 13:19:11 +02002231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
2233 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002234 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2236 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 /* flush useless bits */
2244 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002247 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002248 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
Willy Tarreau1c47f852006-07-09 08:22:27 +02002251 if (!*args[1]) {
2252 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002256 }
2257
Willy Tarreaua534fea2008-08-03 12:19:50 +02002258 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002259 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002260 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002261 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002262 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2263
Willy Tarreau93893792009-07-23 13:19:11 +02002264 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2267 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2268 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2269 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2270 else {
2271 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
2275 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002276 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002277 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002278
2279 if (curproxy == &defproxy) {
2280 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2281 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002284 }
2285
2286 if (!*args[1]) {
2287 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002291 }
2292
2293 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002294 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002295
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002296 if (curproxy->uuid <= 0) {
2297 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002298 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002301 }
2302
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002303 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2304 if (node) {
2305 struct proxy *target = container_of(node, struct proxy, conf.id);
2306 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2307 file, linenum, proxy_type_str(curproxy), curproxy->id,
2308 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002313 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002314 else if (!strcmp(args[0], "description")) {
2315 int i, len=0;
2316 char *d;
2317
Cyril Bonté99ed3272010-01-24 23:29:44 +01002318 if (curproxy == &defproxy) {
2319 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2320 file, linenum, args[0]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002325 if (!*args[1]) {
2326 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2327 file, linenum, args[0]);
2328 return -1;
2329 }
2330
Willy Tarreau348acfe2014-04-14 15:00:39 +02002331 for (i = 1; *args[i]; i++)
2332 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002333
2334 d = (char *)calloc(1, len);
2335 curproxy->desc = d;
2336
Willy Tarreau348acfe2014-04-14 15:00:39 +02002337 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2338 for (i = 2; *args[i]; i++)
2339 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002340
2341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2343 curproxy->state = PR_STSTOPPED;
2344 }
2345 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2346 curproxy->state = PR_STNEW;
2347 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002348 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2349 int cur_arg = 1;
2350 unsigned int set = 0;
2351
2352 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002353 unsigned int low, high;
2354
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002355 if (strcmp(args[cur_arg], "all") == 0) {
2356 set = 0;
2357 break;
2358 }
2359 else if (strcmp(args[cur_arg], "odd") == 0) {
2360 set |= 0x55555555;
2361 }
2362 else if (strcmp(args[cur_arg], "even") == 0) {
2363 set |= 0xAAAAAAAA;
2364 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002365 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002366 char *dash = strchr(args[cur_arg], '-');
2367
2368 low = high = str2uic(args[cur_arg]);
2369 if (dash)
2370 high = str2uic(dash + 1);
2371
2372 if (high < low) {
2373 unsigned int swap = low;
2374 low = high;
2375 high = swap;
2376 }
2377
2378 if (low < 1 || high > 32) {
2379 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002383 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002384
2385 if (high > global.nbproc) {
2386 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2387 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002389 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002390 while (low <= high)
2391 set |= 1 << (low++ - 1);
2392 }
2393 else {
2394 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2395 file, linenum, args[0]);
2396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002398 }
2399 cur_arg++;
2400 }
2401 curproxy->bind_proc = set;
2402 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002403 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002404 if (curproxy == &defproxy) {
2405 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002408 }
2409
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002410 err = invalid_char(args[1]);
2411 if (err) {
2412 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2413 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002415 }
2416
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002417 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002418 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2419 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002422 }
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2425 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 if (*(args[1]) == 0) {
2431 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002436
Willy Tarreau67402132012-05-31 20:40:20 +02002437 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002438 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002439 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002440 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 curproxy->cookie_name = strdup(args[1]);
2442 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002443
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 cur_arg = 2;
2445 while (*(args[cur_arg])) {
2446 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002447 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
2449 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002450 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002453 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 }
2455 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002456 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002459 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002461 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002462 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002463 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002465 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002467 else if (!strcmp(args[cur_arg], "httponly")) {
2468 curproxy->ck_opts |= PR_CK_HTTPONLY;
2469 }
2470 else if (!strcmp(args[cur_arg], "secure")) {
2471 curproxy->ck_opts |= PR_CK_SECURE;
2472 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002473 else if (!strcmp(args[cur_arg], "domain")) {
2474 if (!*args[cur_arg + 1]) {
2475 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2476 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002479 }
2480
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002481 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002482 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002483 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2484 " dots nor does not start with a dot."
2485 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002486 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002487 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002488 }
2489
2490 err = invalid_domainchar(args[cur_arg + 1]);
2491 if (err) {
2492 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2493 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002496 }
2497
Willy Tarreau68a897b2009-12-03 23:28:34 +01002498 if (!curproxy->cookie_domain) {
2499 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2500 } else {
2501 /* one domain was already specified, add another one by
2502 * building the string which will be returned along with
2503 * the cookie.
2504 */
2505 char *new_ptr;
2506 int new_len = strlen(curproxy->cookie_domain) +
2507 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2508 new_ptr = malloc(new_len);
2509 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2510 free(curproxy->cookie_domain);
2511 curproxy->cookie_domain = new_ptr;
2512 }
Willy Tarreau31936852010-10-06 16:59:56 +02002513 cur_arg++;
2514 }
2515 else if (!strcmp(args[cur_arg], "maxidle")) {
2516 unsigned int maxidle;
2517 const char *res;
2518
2519 if (!*args[cur_arg + 1]) {
2520 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2521 file, linenum, args[cur_arg]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
2526 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2527 if (res) {
2528 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2529 file, linenum, *res, args[cur_arg]);
2530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
2532 }
2533 curproxy->cookie_maxidle = maxidle;
2534 cur_arg++;
2535 }
2536 else if (!strcmp(args[cur_arg], "maxlife")) {
2537 unsigned int maxlife;
2538 const char *res;
2539
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2542 file, linenum, args[cur_arg]);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546
2547 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2548 if (res) {
2549 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2550 file, linenum, *res, args[cur_arg]);
2551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
2553 }
2554 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002555 cur_arg++;
2556 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002558 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563 cur_arg++;
2564 }
Willy Tarreau67402132012-05-31 20:40:20 +02002565 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2567 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
Willy Tarreau67402132012-05-31 20:40:20 +02002571 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2573 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002576
Willy Tarreau67402132012-05-31 20:40:20 +02002577 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002578 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2579 file, linenum);
2580 err_code |= ERR_ALERT | ERR_FATAL;
2581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002583 else if (!strcmp(args[0], "persist")) { /* persist */
2584 if (*(args[1]) == 0) {
2585 Alert("parsing [%s:%d] : missing persist method.\n",
2586 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002589 }
2590
2591 if (!strncmp(args[1], "rdp-cookie", 10)) {
2592 curproxy->options2 |= PR_O2_RDPC_PRST;
2593
Emeric Brunb982a3d2010-01-04 15:45:53 +01002594 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002595 const char *beg, *end;
2596
2597 beg = args[1] + 11;
2598 end = strchr(beg, ')');
2599
2600 if (!end || end == beg) {
2601 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2602 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002605 }
2606
2607 free(curproxy->rdp_cookie_name);
2608 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2609 curproxy->rdp_cookie_len = end-beg;
2610 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002611 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002612 free(curproxy->rdp_cookie_name);
2613 curproxy->rdp_cookie_name = strdup("msts");
2614 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2615 }
2616 else { /* syntax */
2617 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2618 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002621 }
2622 }
2623 else {
2624 Alert("parsing [%s:%d] : unknown persist method.\n",
2625 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002628 }
2629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002631 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002633 if (curproxy == &defproxy) {
2634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002641
Willy Tarreaubaaee002006-06-26 02:48:02 +02002642 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002643 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
2648 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002649 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 curproxy->appsession_name = strdup(args[1]);
2651 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2652 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002653 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2654 if (err) {
2655 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2656 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002659 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002660 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002661
Willy Tarreau51041c72007-09-09 21:56:53 +02002662 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2663 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_ABORT;
2665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002667
2668 cur_arg = 6;
2669 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002670 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2671 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002672 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002673 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002674 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002675 } else if (!strcmp(args[cur_arg], "prefix")) {
2676 curproxy->options2 |= PR_O2_AS_PFX;
2677 } else if (!strcmp(args[cur_arg], "mode")) {
2678 if (!*args[cur_arg + 1]) {
2679 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2680 file, linenum, args[0], args[cur_arg]);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
2685 cur_arg++;
2686 if (!strcmp(args[cur_arg], "query-string")) {
2687 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2688 curproxy->options2 |= PR_O2_AS_M_QS;
2689 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2690 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2691 curproxy->options2 |= PR_O2_AS_M_PP;
2692 } else {
2693 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002698 cur_arg++;
2699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 } /* Url App Session */
2701 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002706 if (curproxy == &defproxy) {
2707 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 if (*(args[4]) == 0) {
2713 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002718 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 curproxy->capture_name = strdup(args[2]);
2720 curproxy->capture_namelen = strlen(curproxy->capture_name);
2721 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 curproxy->to_log |= LW_COOKIE;
2723 }
2724 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2725 struct cap_hdr *hdr;
2726
2727 if (curproxy == &defproxy) {
2728 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 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
2732
2733 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2734 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2735 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 }
2739
2740 hdr = calloc(sizeof(struct cap_hdr), 1);
2741 hdr->next = curproxy->req_cap;
2742 hdr->name = strdup(args[3]);
2743 hdr->namelen = strlen(args[3]);
2744 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002745 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 hdr->index = curproxy->nb_req_cap++;
2747 curproxy->req_cap = hdr;
2748 curproxy->to_log |= LW_REQHDR;
2749 }
2750 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2751 struct cap_hdr *hdr;
2752
2753 if (curproxy == &defproxy) {
2754 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 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758
2759 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2760 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2761 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 hdr = calloc(sizeof(struct cap_hdr), 1);
2766 hdr->next = curproxy->rsp_cap;
2767 hdr->name = strdup(args[3]);
2768 hdr->namelen = strlen(args[3]);
2769 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002770 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 hdr->index = curproxy->nb_rsp_cap++;
2772 curproxy->rsp_cap = hdr;
2773 curproxy->to_log |= LW_RSPHDR;
2774 }
2775 else {
2776 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2777 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
2781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002785
Willy Tarreaubaaee002006-06-26 02:48:02 +02002786 if (*(args[1]) == 0) {
2787 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 }
2792 curproxy->conn_retries = atol(args[1]);
2793 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002794 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002795 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002796
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
Willy Tarreau20b0de52012-12-24 15:45:22 +01002803 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2804 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2805 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2806 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002807 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002808 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2809 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 +01002810 file, linenum, args[0]);
2811 err_code |= ERR_WARN;
2812 }
2813
Willy Tarreauff011f22011-01-06 17:51:27 +01002814 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002815
Willy Tarreauff011f22011-01-06 17:51:27 +01002816 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002817 err_code |= ERR_ALERT | ERR_ABORT;
2818 goto out;
2819 }
2820
Willy Tarreau5002f572014-04-23 01:32:02 +02002821 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002822 err_code |= warnif_cond_conflicts(rule->cond,
2823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2824 file, linenum);
2825
Willy Tarreauff011f22011-01-06 17:51:27 +01002826 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002827 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002828 else if (!strcmp(args[0], "http-response")) { /* response access control */
2829 struct http_res_rule *rule;
2830
2831 if (curproxy == &defproxy) {
2832 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
2837 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2838 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2839 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2840 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2841 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2842 file, linenum, args[0]);
2843 err_code |= ERR_WARN;
2844 }
2845
2846 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2847
2848 if (!rule) {
2849 err_code |= ERR_ALERT | ERR_ABORT;
2850 goto out;
2851 }
2852
2853 err_code |= warnif_cond_conflicts(rule->cond,
2854 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2855 file, linenum);
2856
2857 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2858 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002859 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2860 /* set the header name and length into the proxy structure */
2861 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2862 err_code |= ERR_WARN;
2863
2864 if (!*args[1]) {
2865 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2866 file, linenum, args[0]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870
2871 /* set the desired header name */
2872 free(curproxy->server_id_hdr_name);
2873 curproxy->server_id_hdr_name = strdup(args[1]);
2874 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2875 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002876 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002877 struct http_req_rule *rule;
2878
Willy Tarreaub099aca2008-10-12 17:26:37 +02002879 if (curproxy == &defproxy) {
2880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002883 }
2884
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002885 /* emulate "block" using "http-request block". Since these rules are supposed to
2886 * be processed before all http-request rules, we put them into their own list
2887 * and will insert them at the end.
2888 */
2889 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
2890 if (!rule) {
2891 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02002892 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002893 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002894 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
2895 err_code |= warnif_cond_conflicts(rule->cond,
2896 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2897 file, linenum);
2898 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02002899
2900 if (!already_warned(WARN_BLOCK_DEPRECATED))
2901 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]);
2902
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002903 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002904 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002905 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002906
Cyril Bonté99ed3272010-01-24 23:29:44 +01002907 if (curproxy == &defproxy) {
2908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002913 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002914 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2915 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002918 }
2919
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002920 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02002921 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002922 err_code |= warnif_cond_conflicts(rule->cond,
2923 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2924 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002925 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002926 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002927 struct switching_rule *rule;
2928
Willy Tarreaub099aca2008-10-12 17:26:37 +02002929 if (curproxy == &defproxy) {
2930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002933 }
2934
Willy Tarreau55ea7572007-06-17 19:56:27 +02002935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002936 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002937
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002942 }
2943
Willy Tarreauf51658d2014-04-23 01:21:56 +02002944 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
2945 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2946 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2947 file, linenum, errmsg);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02002951
Willy Tarreauf51658d2014-04-23 01:21:56 +02002952 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02002953 }
2954
2955 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2956 rule->cond = cond;
2957 rule->be.name = strdup(args[1]);
2958 LIST_INIT(&rule->list);
2959 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2960 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002961 else if (strcmp(args[0], "use-server") == 0) {
2962 struct server_rule *rule;
2963
2964 if (curproxy == &defproxy) {
2965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
2969
2970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2971 err_code |= ERR_WARN;
2972
2973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
2977 }
2978
2979 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2980 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2981 file, linenum, args[0]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002986 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2987 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2988 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002993 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002994
2995 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2996 rule->cond = cond;
2997 rule->srv.name = strdup(args[1]);
2998 LIST_INIT(&rule->list);
2999 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3000 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3001 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003002 else if ((!strcmp(args[0], "force-persist")) ||
3003 (!strcmp(args[0], "ignore-persist"))) {
3004 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003005
3006 if (curproxy == &defproxy) {
3007 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011
3012 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3013 err_code |= ERR_WARN;
3014
Willy Tarreauef6494c2010-01-28 17:12:36 +01003015 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003016 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3017 file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003022 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3023 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3024 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
3028
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003029 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3030 * where force-persist is applied.
3031 */
3032 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003033
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003034 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003035 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003036 if (!strcmp(args[0], "force-persist")) {
3037 rule->type = PERSIST_TYPE_FORCE;
3038 } else {
3039 rule->type = PERSIST_TYPE_IGNORE;
3040 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003041 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003042 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003043 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 else if (!strcmp(args[0], "stick-table")) {
3045 int myidx = 1;
3046
Emeric Brun32da3c42010-09-23 18:39:19 +02003047 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 curproxy->table.type = (unsigned int)-1;
3049 while (*args[myidx]) {
3050 const char *err;
3051
3052 if (strcmp(args[myidx], "size") == 0) {
3053 myidx++;
3054 if (!*(args[myidx])) {
3055 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3056 file, linenum, args[myidx-1]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3061 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3062 file, linenum, *err, args[myidx-1]);
3063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
3065 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003066 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003068 else if (strcmp(args[myidx], "peers") == 0) {
3069 myidx++;
Godbach50523162013-12-11 19:48:57 +08003070 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003071 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3072 file, linenum, args[myidx-1]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Godbach50523162013-12-11 19:48:57 +08003075 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003076 curproxy->table.peers.name = strdup(args[myidx++]);
3077 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003078 else if (strcmp(args[myidx], "expire") == 0) {
3079 myidx++;
3080 if (!*(args[myidx])) {
3081 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3082 file, linenum, args[myidx-1]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3087 if (err) {
3088 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3089 file, linenum, *err, args[myidx-1]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003094 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003095 }
3096 else if (strcmp(args[myidx], "nopurge") == 0) {
3097 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003098 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003099 }
3100 else if (strcmp(args[myidx], "type") == 0) {
3101 myidx++;
3102 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3103 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3104 file, linenum, args[myidx]);
3105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
3107 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003108 /* myidx already points to next arg */
3109 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003110 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003111 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003112 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003113
3114 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003115 nw = args[myidx];
3116 while (*nw) {
3117 /* the "store" keyword supports a comma-separated list */
3118 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003119 sa = NULL; /* store arg */
3120 while (*nw && *nw != ',') {
3121 if (*nw == '(') {
3122 *nw = 0;
3123 sa = ++nw;
3124 while (*nw != ')') {
3125 if (!*nw) {
3126 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3127 file, linenum, args[0], cw);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131 nw++;
3132 }
3133 *nw = '\0';
3134 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003135 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003136 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003137 if (*nw)
3138 *nw++ = '\0';
3139 type = stktable_get_data_type(cw);
3140 if (type < 0) {
3141 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3142 file, linenum, args[0], cw);
3143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
3145 }
Willy Tarreauac782882010-06-20 10:41:54 +02003146
3147 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3148 switch (err) {
3149 case PE_NONE: break;
3150 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003151 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3152 file, linenum, args[0], cw);
3153 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003154 break;
3155
3156 case PE_ARG_MISSING:
3157 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3158 file, linenum, args[0], cw);
3159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
3161
3162 case PE_ARG_NOT_USED:
3163 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3164 file, linenum, args[0], cw);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167
3168 default:
3169 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3170 file, linenum, args[0], cw);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003173 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003174 }
3175 myidx++;
3176 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003177 else {
3178 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3179 file, linenum, args[myidx]);
3180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003182 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003183 }
3184
3185 if (!curproxy->table.size) {
3186 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3187 file, linenum);
3188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
3190 }
3191
3192 if (curproxy->table.type == (unsigned int)-1) {
3193 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3194 file, linenum);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
3198 }
3199 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003200 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003201 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003202 int myidx = 0;
3203 const char *name = NULL;
3204 int flags;
3205
3206 if (curproxy == &defproxy) {
3207 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211
3212 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3213 err_code |= ERR_WARN;
3214 goto out;
3215 }
3216
3217 myidx++;
3218 if ((strcmp(args[myidx], "store") == 0) ||
3219 (strcmp(args[myidx], "store-request") == 0)) {
3220 myidx++;
3221 flags = STK_IS_STORE;
3222 }
3223 else if (strcmp(args[myidx], "store-response") == 0) {
3224 myidx++;
3225 flags = STK_IS_STORE | STK_ON_RSP;
3226 }
3227 else if (strcmp(args[myidx], "match") == 0) {
3228 myidx++;
3229 flags = STK_IS_MATCH;
3230 }
3231 else if (strcmp(args[myidx], "on") == 0) {
3232 myidx++;
3233 flags = STK_IS_MATCH | STK_IS_STORE;
3234 }
3235 else {
3236 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240
3241 if (*(args[myidx]) == 0) {
3242 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
3246
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003247 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003248 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003250 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
3254
3255 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003256 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3257 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3258 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003259 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003260 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003261 goto out;
3262 }
3263 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003264 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3265 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3266 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003267 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003268 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003269 goto out;
3270 }
3271 }
3272
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003273 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003274 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003275
Emeric Brunb982a3d2010-01-04 15:45:53 +01003276 if (strcmp(args[myidx], "table") == 0) {
3277 myidx++;
3278 name = args[myidx++];
3279 }
3280
Willy Tarreauef6494c2010-01-28 17:12:36 +01003281 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003282 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3283 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3284 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003285 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003286 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003287 goto out;
3288 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003289 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003290 else if (*(args[myidx])) {
3291 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3292 file, linenum, args[0], args[myidx]);
3293 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003294 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003295 goto out;
3296 }
Emeric Brun97679e72010-09-23 17:56:44 +02003297 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003298 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003299 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003300 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003301
Emeric Brunb982a3d2010-01-04 15:45:53 +01003302 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3303 rule->cond = cond;
3304 rule->expr = expr;
3305 rule->flags = flags;
3306 rule->table.name = name ? strdup(name) : NULL;
3307 LIST_INIT(&rule->list);
3308 if (flags & STK_ON_RSP)
3309 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3310 else
3311 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3312 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 else if (!strcmp(args[0], "stats")) {
3314 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3315 curproxy->uri_auth = NULL; /* we must detach from the default config */
3316
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003317 if (!*args[1]) {
3318 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003319 } else if (!strcmp(args[1], "admin")) {
3320 struct stats_admin_rule *rule;
3321
3322 if (curproxy == &defproxy) {
3323 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
3327
3328 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3329 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3330 err_code |= ERR_ALERT | ERR_ABORT;
3331 goto out;
3332 }
3333
3334 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3335 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3336 file, linenum, args[0], args[1]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003340 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3341 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3342 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003343 err_code |= ERR_ALERT | ERR_FATAL;
3344 goto out;
3345 }
3346
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003347 err_code |= warnif_cond_conflicts(cond,
3348 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3349 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003350
3351 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3352 rule->cond = cond;
3353 LIST_INIT(&rule->list);
3354 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 } else if (!strcmp(args[1], "uri")) {
3356 if (*(args[2]) == 0) {
3357 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003362 err_code |= ERR_ALERT | ERR_ABORT;
3363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
3365 } else if (!strcmp(args[1], "realm")) {
3366 if (*(args[2]) == 0) {
3367 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_ABORT;
3373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003375 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003376 unsigned interval;
3377
3378 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3379 if (err) {
3380 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3381 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003384 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_ABORT;
3387 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003388 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003389 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003390 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003391
3392 if (curproxy == &defproxy) {
3393 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3394 err_code |= ERR_ALERT | ERR_FATAL;
3395 goto out;
3396 }
3397
3398 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3399 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3400 err_code |= ERR_ALERT | ERR_ABORT;
3401 goto out;
3402 }
3403
Willy Tarreauff011f22011-01-06 17:51:27 +01003404 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3405 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003406 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3407 file, linenum, args[0]);
3408 err_code |= ERR_WARN;
3409 }
3410
Willy Tarreauff011f22011-01-06 17:51:27 +01003411 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003412
Willy Tarreauff011f22011-01-06 17:51:27 +01003413 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003414 err_code |= ERR_ALERT | ERR_ABORT;
3415 goto out;
3416 }
3417
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003418 err_code |= warnif_cond_conflicts(rule->cond,
3419 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3420 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003421 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003422
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 } else if (!strcmp(args[1], "auth")) {
3424 if (*(args[2]) == 0) {
3425 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3429 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_ALERT | ERR_ABORT;
3431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
3433 } else if (!strcmp(args[1], "scope")) {
3434 if (*(args[2]) == 0) {
3435 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3439 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003440 err_code |= ERR_ALERT | ERR_ABORT;
3441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 }
3443 } else if (!strcmp(args[1], "enable")) {
3444 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3445 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_ALERT | ERR_ABORT;
3447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003449 } else if (!strcmp(args[1], "hide-version")) {
3450 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3451 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003452 err_code |= ERR_ALERT | ERR_ABORT;
3453 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003454 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003455 } else if (!strcmp(args[1], "show-legends")) {
3456 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3457 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3458 err_code |= ERR_ALERT | ERR_ABORT;
3459 goto out;
3460 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003461 } else if (!strcmp(args[1], "show-node")) {
3462
3463 if (*args[2]) {
3464 int i;
3465 char c;
3466
3467 for (i=0; args[2][i]; i++) {
3468 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003469 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3470 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003471 break;
3472 }
3473
3474 if (!i || args[2][i]) {
3475 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3476 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3477 file, linenum, args[0], args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481 }
3482
3483 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3485 err_code |= ERR_ALERT | ERR_ABORT;
3486 goto out;
3487 }
3488 } else if (!strcmp(args[1], "show-desc")) {
3489 char *desc = NULL;
3490
3491 if (*args[2]) {
3492 int i, len=0;
3493 char *d;
3494
Willy Tarreau348acfe2014-04-14 15:00:39 +02003495 for (i = 2; *args[i]; i++)
3496 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003497
3498 desc = d = (char *)calloc(1, len);
3499
Willy Tarreau348acfe2014-04-14 15:00:39 +02003500 d += snprintf(d, desc + len - d, "%s", args[2]);
3501 for (i = 3; *args[i]; i++)
3502 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003503 }
3504
3505 if (!*args[2] && !global.desc)
3506 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3507 file, linenum, args[1]);
3508 else {
3509 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3510 free(desc);
3511 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3512 err_code |= ERR_ALERT | ERR_ABORT;
3513 goto out;
3514 }
3515 free(desc);
3516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003518stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003519 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 +01003520 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 }
3524 }
3525 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003526 int optnum;
3527
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003528 if (*(args[1]) == '\0') {
3529 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003534
3535 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3536 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003537 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3538 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3539 file, linenum, cfg_opts[optnum].name);
3540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
3542 }
Willy Tarreau93893792009-07-23 13:19:11 +02003543 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3544 err_code |= ERR_WARN;
3545 goto out;
3546 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003547
Willy Tarreau3842f002009-06-14 11:39:52 +02003548 curproxy->no_options &= ~cfg_opts[optnum].val;
3549 curproxy->options &= ~cfg_opts[optnum].val;
3550
3551 switch (kwm) {
3552 case KWM_STD:
3553 curproxy->options |= cfg_opts[optnum].val;
3554 break;
3555 case KWM_NO:
3556 curproxy->no_options |= cfg_opts[optnum].val;
3557 break;
3558 case KWM_DEF: /* already cleared */
3559 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003560 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003561
Willy Tarreau93893792009-07-23 13:19:11 +02003562 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003563 }
3564 }
3565
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003566 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3567 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003568 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3569 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3570 file, linenum, cfg_opts2[optnum].name);
3571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
3573 }
Willy Tarreau93893792009-07-23 13:19:11 +02003574 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3575 err_code |= ERR_WARN;
3576 goto out;
3577 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003578
Willy Tarreau3842f002009-06-14 11:39:52 +02003579 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3580 curproxy->options2 &= ~cfg_opts2[optnum].val;
3581
3582 switch (kwm) {
3583 case KWM_STD:
3584 curproxy->options2 |= cfg_opts2[optnum].val;
3585 break;
3586 case KWM_NO:
3587 curproxy->no_options2 |= cfg_opts2[optnum].val;
3588 break;
3589 case KWM_DEF: /* already cleared */
3590 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003591 }
Willy Tarreau93893792009-07-23 13:19:11 +02003592 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003593 }
3594 }
3595
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003596 /* HTTP options override each other. They can be cancelled using
3597 * "no option xxx" which only switches to default mode if the mode
3598 * was this one (useful for cancelling options set in defaults
3599 * sections).
3600 */
3601 if (strcmp(args[1], "httpclose") == 0) {
3602 if (kwm == KWM_STD) {
3603 curproxy->options &= ~PR_O_HTTP_MODE;
3604 curproxy->options |= PR_O_HTTP_PCL;
3605 goto out;
3606 }
3607 else if (kwm == KWM_NO) {
3608 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3609 curproxy->options &= ~PR_O_HTTP_MODE;
3610 goto out;
3611 }
3612 }
3613 else if (strcmp(args[1], "forceclose") == 0) {
3614 if (kwm == KWM_STD) {
3615 curproxy->options &= ~PR_O_HTTP_MODE;
3616 curproxy->options |= PR_O_HTTP_FCL;
3617 goto out;
3618 }
3619 else if (kwm == KWM_NO) {
3620 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3621 curproxy->options &= ~PR_O_HTTP_MODE;
3622 goto out;
3623 }
3624 }
3625 else if (strcmp(args[1], "http-server-close") == 0) {
3626 if (kwm == KWM_STD) {
3627 curproxy->options &= ~PR_O_HTTP_MODE;
3628 curproxy->options |= PR_O_HTTP_SCL;
3629 goto out;
3630 }
3631 else if (kwm == KWM_NO) {
3632 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3633 curproxy->options &= ~PR_O_HTTP_MODE;
3634 goto out;
3635 }
3636 }
3637 else if (strcmp(args[1], "http-keep-alive") == 0) {
3638 if (kwm == KWM_STD) {
3639 curproxy->options &= ~PR_O_HTTP_MODE;
3640 curproxy->options |= PR_O_HTTP_KAL;
3641 goto out;
3642 }
3643 else if (kwm == KWM_NO) {
3644 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3645 curproxy->options &= ~PR_O_HTTP_MODE;
3646 goto out;
3647 }
3648 }
3649 else if (strcmp(args[1], "http-tunnel") == 0) {
3650 if (kwm == KWM_STD) {
3651 curproxy->options &= ~PR_O_HTTP_MODE;
3652 curproxy->options |= PR_O_HTTP_TUN;
3653 goto out;
3654 }
3655 else if (kwm == KWM_NO) {
3656 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3657 curproxy->options &= ~PR_O_HTTP_MODE;
3658 goto out;
3659 }
3660 }
3661
Willy Tarreau3842f002009-06-14 11:39:52 +02003662 if (kwm != KWM_STD) {
3663 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003664 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003667 }
3668
Emeric Brun3a058f32009-06-30 18:26:00 +02003669 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003670 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003672 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003673 if (*(args[2]) != '\0') {
3674 if (!strcmp(args[2], "clf")) {
3675 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003676 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003677 } else {
3678 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003681 }
3682 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003683 if (curproxy->conf.logformat_string != default_http_log_format &&
3684 curproxy->conf.logformat_string != default_tcp_log_format &&
3685 curproxy->conf.logformat_string != clf_http_log_format)
3686 free(curproxy->conf.logformat_string);
3687 curproxy->conf.logformat_string = logformat;
3688
3689 free(curproxy->conf.lfs_file);
3690 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3691 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003692 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003693 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003695 if (curproxy->conf.logformat_string != default_http_log_format &&
3696 curproxy->conf.logformat_string != default_tcp_log_format &&
3697 curproxy->conf.logformat_string != clf_http_log_format)
3698 free(curproxy->conf.logformat_string);
3699 curproxy->conf.logformat_string = default_tcp_log_format;
3700
3701 free(curproxy->conf.lfs_file);
3702 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3703 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 else if (!strcmp(args[1], "tcpka")) {
3706 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003707 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003709
3710 if (curproxy->cap & PR_CAP_FE)
3711 curproxy->options |= PR_O_TCP_CLI_KA;
3712 if (curproxy->cap & PR_CAP_BE)
3713 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 }
3715 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_WARN;
3718
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003720 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003721 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003722 curproxy->options2 &= ~PR_O2_CHK_ANY;
3723 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 if (!*args[2]) { /* no argument */
3725 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3726 curproxy->check_len = strlen(DEF_CHECK_REQ);
3727 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003728 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 curproxy->check_req = (char *)malloc(reqlen);
3730 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003731 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003733 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 if (*args[4])
3735 reqlen += strlen(args[4]);
3736 else
3737 reqlen += strlen("HTTP/1.0");
3738
3739 curproxy->check_req = (char *)malloc(reqlen);
3740 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003741 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003743 }
3744 else if (!strcmp(args[1], "ssl-hello-chk")) {
3745 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003746 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003748
Willy Tarreaua534fea2008-08-03 12:19:50 +02003749 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003750 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003751 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003752 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003753 }
Willy Tarreau23677902007-05-08 23:50:35 +02003754 else if (!strcmp(args[1], "smtpchk")) {
3755 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003756 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003757 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003758 curproxy->options2 &= ~PR_O2_CHK_ANY;
3759 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003760
3761 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3762 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3763 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3764 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3765 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3766 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3767 curproxy->check_req = (char *)malloc(reqlen);
3768 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3769 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3770 } else {
3771 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3772 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3773 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3774 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3775 }
3776 }
3777 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003778 else if (!strcmp(args[1], "pgsql-check")) {
3779 /* use PostgreSQL request to check servers' health */
3780 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3781 err_code |= ERR_WARN;
3782
3783 free(curproxy->check_req);
3784 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003785 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003786 curproxy->options2 |= PR_O2_PGSQL_CHK;
3787
3788 if (*(args[2])) {
3789 int cur_arg = 2;
3790
3791 while (*(args[cur_arg])) {
3792 if (strcmp(args[cur_arg], "user") == 0) {
3793 char * packet;
3794 uint32_t packet_len;
3795 uint32_t pv;
3796
3797 /* suboption header - needs additional argument for it */
3798 if (*(args[cur_arg+1]) == 0) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3800 file, linenum, args[0], args[1], args[cur_arg]);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804
3805 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3806 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3807 pv = htonl(0x30000); /* protocol version 3.0 */
3808
3809 packet = (char*) calloc(1, packet_len);
3810
3811 memcpy(packet + 4, &pv, 4);
3812
3813 /* copy "user" */
3814 memcpy(packet + 8, "user", 4);
3815
3816 /* copy username */
3817 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3818
3819 free(curproxy->check_req);
3820 curproxy->check_req = packet;
3821 curproxy->check_len = packet_len;
3822
3823 packet_len = htonl(packet_len);
3824 memcpy(packet, &packet_len, 4);
3825 cur_arg += 2;
3826 } else {
3827 /* unknown suboption - catchall */
3828 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3829 file, linenum, args[0], args[1]);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833 } /* end while loop */
3834 }
3835 }
3836
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003837 else if (!strcmp(args[1], "redis-check")) {
3838 /* use REDIS PING request to check servers' health */
3839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3840 err_code |= ERR_WARN;
3841
3842 free(curproxy->check_req);
3843 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003844 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003845 curproxy->options2 |= PR_O2_REDIS_CHK;
3846
3847 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3848 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3849 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3850 }
3851
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003852 else if (!strcmp(args[1], "mysql-check")) {
3853 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3855 err_code |= ERR_WARN;
3856
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003857 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003858 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003859 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003860 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003861
3862 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3863 * const char mysql40_client_auth_pkt[] = {
3864 * "\x0e\x00\x00" // packet length
3865 * "\x01" // packet number
3866 * "\x00\x00" // client capabilities
3867 * "\x00\x00\x01" // max packet
3868 * "haproxy\x00" // username (null terminated string)
3869 * "\x00" // filler (always 0x00)
3870 * "\x01\x00\x00" // packet length
3871 * "\x00" // packet number
3872 * "\x01" // COM_QUIT command
3873 * };
3874 */
3875
3876 if (*(args[2])) {
3877 int cur_arg = 2;
3878
3879 while (*(args[cur_arg])) {
3880 if (strcmp(args[cur_arg], "user") == 0) {
3881 char *mysqluser;
3882 int packetlen, reqlen, userlen;
3883
3884 /* suboption header - needs additional argument for it */
3885 if (*(args[cur_arg+1]) == 0) {
3886 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3887 file, linenum, args[0], args[1], args[cur_arg]);
3888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
3890 }
3891 mysqluser = args[cur_arg + 1];
3892 userlen = strlen(mysqluser);
3893 packetlen = userlen + 7;
3894 reqlen = packetlen + 9;
3895
3896 free(curproxy->check_req);
3897 curproxy->check_req = (char *)calloc(1, reqlen);
3898 curproxy->check_len = reqlen;
3899
3900 snprintf(curproxy->check_req, 4, "%c%c%c",
3901 ((unsigned char) packetlen & 0xff),
3902 ((unsigned char) (packetlen >> 8) & 0xff),
3903 ((unsigned char) (packetlen >> 16) & 0xff));
3904
3905 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003906 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003907 curproxy->check_req[8] = 1;
3908 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3909 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3910 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3911 cur_arg += 2;
3912 } else {
3913 /* unknown suboption - catchall */
3914 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3915 file, linenum, args[0], args[1]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919 } /* end while loop */
3920 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003921 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003922 else if (!strcmp(args[1], "ldap-check")) {
3923 /* use LDAP request to check servers' health */
3924 free(curproxy->check_req);
3925 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003926 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003927 curproxy->options2 |= PR_O2_LDAP_CHK;
3928
3929 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3930 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3931 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3932 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003933 else if (!strcmp(args[1], "tcp-check")) {
3934 /* use raw TCPCHK send/expect to check servers' health */
3935 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3936 err_code |= ERR_WARN;
3937
3938 free(curproxy->check_req);
3939 curproxy->check_req = NULL;
3940 curproxy->options2 &= ~PR_O2_CHK_ANY;
3941 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3942 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003943 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003944 int cur_arg;
3945
3946 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3947 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003948 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003949
Willy Tarreau87cf5142011-08-19 22:57:24 +02003950 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003951
3952 free(curproxy->fwdfor_hdr_name);
3953 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3954 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3955
3956 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3957 cur_arg = 2;
3958 while (*(args[cur_arg])) {
3959 if (!strcmp(args[cur_arg], "except")) {
3960 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003961 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003962 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3963 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003966 }
3967 /* flush useless bits */
3968 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003969 cur_arg += 2;
3970 } else if (!strcmp(args[cur_arg], "header")) {
3971 /* suboption header - needs additional argument for it */
3972 if (*(args[cur_arg+1]) == 0) {
3973 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003977 }
3978 free(curproxy->fwdfor_hdr_name);
3979 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3980 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3981 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003982 } else if (!strcmp(args[cur_arg], "if-none")) {
3983 curproxy->options &= ~PR_O_FF_ALWAYS;
3984 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003985 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003986 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003987 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003988 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003991 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003992 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003993 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003994 else if (!strcmp(args[1], "originalto")) {
3995 int cur_arg;
3996
3997 /* insert x-original-to field, but not for the IP address listed as an except.
3998 * set default options (ie: bitfield, header name, etc)
3999 */
4000
4001 curproxy->options |= PR_O_ORGTO;
4002
4003 free(curproxy->orgto_hdr_name);
4004 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4005 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4006
Willy Tarreau87cf5142011-08-19 22:57:24 +02004007 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004008 cur_arg = 2;
4009 while (*(args[cur_arg])) {
4010 if (!strcmp(args[cur_arg], "except")) {
4011 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004012 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 +02004013 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4014 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004017 }
4018 /* flush useless bits */
4019 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4020 cur_arg += 2;
4021 } else if (!strcmp(args[cur_arg], "header")) {
4022 /* suboption header - needs additional argument for it */
4023 if (*(args[cur_arg+1]) == 0) {
4024 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4025 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004028 }
4029 free(curproxy->orgto_hdr_name);
4030 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4031 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4032 cur_arg += 2;
4033 } else {
4034 /* unknown suboption - catchall */
4035 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4036 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004039 }
4040 } /* end while loop */
4041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 else {
4043 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 }
Willy Tarreau93893792009-07-23 13:19:11 +02004047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004049 else if (!strcmp(args[0], "default_backend")) {
4050 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004052
4053 if (*(args[1]) == 0) {
4054 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004057 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004058 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004059 curproxy->defbe.name = strdup(args[1]);
4060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004064
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004065 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004067 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 /* enable reconnections to dispatch */
4069 curproxy->options |= PR_O_REDISP;
4070 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004071 else if (!strcmp(args[0], "http-check")) {
4072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004074
4075 if (strcmp(args[1], "disable-on-404") == 0) {
4076 /* enable a graceful server shutdown on an HTTP 404 response */
4077 curproxy->options |= PR_O_DISABLE404;
4078 }
Willy Tarreauef781042010-01-27 11:53:01 +01004079 else if (strcmp(args[1], "send-state") == 0) {
4080 /* enable emission of the apparent state of a server in HTTP checks */
4081 curproxy->options2 |= PR_O2_CHK_SNDST;
4082 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004083 else if (strcmp(args[1], "expect") == 0) {
4084 const char *ptr_arg;
4085 int cur_arg;
4086
4087 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4088 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092
4093 cur_arg = 2;
4094 /* consider exclamation marks, sole or at the beginning of a word */
4095 while (*(ptr_arg = args[cur_arg])) {
4096 while (*ptr_arg == '!') {
4097 curproxy->options2 ^= PR_O2_EXP_INV;
4098 ptr_arg++;
4099 }
4100 if (*ptr_arg)
4101 break;
4102 cur_arg++;
4103 }
4104 /* now ptr_arg points to the beginning of a word past any possible
4105 * exclamation mark, and cur_arg is the argument which holds this word.
4106 */
4107 if (strcmp(ptr_arg, "status") == 0) {
4108 if (!*(args[cur_arg + 1])) {
4109 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4110 file, linenum, args[0], args[1], ptr_arg);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
4114 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004115 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004116 curproxy->expect_str = strdup(args[cur_arg + 1]);
4117 }
4118 else if (strcmp(ptr_arg, "string") == 0) {
4119 if (!*(args[cur_arg + 1])) {
4120 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4121 file, linenum, args[0], args[1], ptr_arg);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004126 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004127 curproxy->expect_str = strdup(args[cur_arg + 1]);
4128 }
4129 else if (strcmp(ptr_arg, "rstatus") == 0) {
4130 if (!*(args[cur_arg + 1])) {
4131 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4132 file, linenum, args[0], args[1], ptr_arg);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004137 free(curproxy->expect_str);
4138 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4139 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004140 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4141 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4142 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4143 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147 }
4148 else if (strcmp(ptr_arg, "rstring") == 0) {
4149 if (!*(args[cur_arg + 1])) {
4150 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4151 file, linenum, args[0], args[1], ptr_arg);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004156 free(curproxy->expect_str);
4157 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4158 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004159 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4160 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4161 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4162 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166 }
4167 else {
4168 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4169 file, linenum, args[0], args[1], ptr_arg);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004174 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004175 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 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004178 }
4179 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004180 else if (!strcmp(args[0], "tcp-check")) {
4181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4182 err_code |= ERR_WARN;
4183
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004184 if (strcmp(args[1], "connect") == 0) {
4185 const char *ptr_arg;
4186 int cur_arg;
4187 struct tcpcheck_rule *tcpcheck;
4188 struct list *l;
4189
4190 /* check if first rule is also a 'connect' action */
4191 l = (struct list *)&curproxy->tcpcheck_rules;
4192 if (l->p != l->n) {
4193 tcpcheck = (struct tcpcheck_rule *)l->n;
4194 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4195 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4196 file, linenum);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
4200 }
4201
4202 cur_arg = 2;
4203 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4204 tcpcheck->action = TCPCHK_ACT_CONNECT;
4205
4206 /* parsing each parameters to fill up the rule */
4207 while (*(ptr_arg = args[cur_arg])) {
4208 /* tcp port */
4209 if (strcmp(args[cur_arg], "port") == 0) {
4210 if ( (atol(args[cur_arg + 1]) > 65535) ||
4211 (atol(args[cur_arg + 1]) < 1) ){
4212 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4213 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217 tcpcheck->port = atol(args[cur_arg + 1]);
4218 cur_arg += 2;
4219 }
4220 /* send proxy protocol */
4221 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4222 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4223 cur_arg++;
4224 }
4225#ifdef USE_OPENSSL
4226 else if (strcmp(args[cur_arg], "ssl") == 0) {
4227 curproxy->options |= PR_O_TCPCHK_SSL;
4228 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4229 cur_arg++;
4230 }
4231#endif /* USE_OPENSSL */
4232 else {
4233#ifdef USE_OPENSSL
4234 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4235#else /* USE_OPENSSL */
4236 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4237#endif /* USE_OPENSSL */
4238 file, linenum, args[0], args[1], args[cur_arg]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242
4243 }
4244
4245 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4246 }
4247 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004248 if (! *(args[2]) ) {
4249 /* SEND string expected */
4250 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4251 file, linenum, args[0], args[1], args[2]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 } else {
4255 struct tcpcheck_rule *tcpcheck;
4256
4257 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4258
4259 tcpcheck->action = TCPCHK_ACT_SEND;
4260 tcpcheck->string_len = strlen(args[2]);
4261 tcpcheck->string = strdup(args[2]);
4262 tcpcheck->expect_regex = NULL;
4263
4264 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4265 }
4266 }
4267 else if (strcmp(args[1], "send-binary") == 0) {
4268 if (! *(args[2]) ) {
4269 /* SEND binary string expected */
4270 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4271 file, linenum, args[0], args[1], args[2]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 } else {
4275 struct tcpcheck_rule *tcpcheck;
4276 char *err = NULL;
4277
4278 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4279
4280 tcpcheck->action = TCPCHK_ACT_SEND;
4281 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4282 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4283 file, linenum, args[0], args[1], args[2], err);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287 tcpcheck->expect_regex = NULL;
4288
4289 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4290 }
4291 }
4292 else if (strcmp(args[1], "expect") == 0) {
4293 const char *ptr_arg;
4294 int cur_arg;
4295 int inverse = 0;
4296
4297 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4298 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
4301 }
4302
4303 cur_arg = 2;
4304 /* consider exclamation marks, sole or at the beginning of a word */
4305 while (*(ptr_arg = args[cur_arg])) {
4306 while (*ptr_arg == '!') {
4307 inverse = !inverse;
4308 ptr_arg++;
4309 }
4310 if (*ptr_arg)
4311 break;
4312 cur_arg++;
4313 }
4314 /* now ptr_arg points to the beginning of a word past any possible
4315 * exclamation mark, and cur_arg is the argument which holds this word.
4316 */
4317 if (strcmp(ptr_arg, "binary") == 0) {
4318 if (!*(args[cur_arg + 1])) {
4319 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4320 file, linenum, args[0], args[1], ptr_arg);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 struct tcpcheck_rule *tcpcheck;
4325 char *err = NULL;
4326
4327 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4328
4329 tcpcheck->action = TCPCHK_ACT_EXPECT;
4330 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4331 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4332 file, linenum, args[0], args[1], args[2], err);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336 tcpcheck->expect_regex = NULL;
4337 tcpcheck->inverse = inverse;
4338
4339 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4340 }
4341 else if (strcmp(ptr_arg, "string") == 0) {
4342 if (!*(args[cur_arg + 1])) {
4343 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4344 file, linenum, args[0], args[1], ptr_arg);
4345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
4347 }
4348 struct tcpcheck_rule *tcpcheck;
4349
4350 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4351
4352 tcpcheck->action = TCPCHK_ACT_EXPECT;
4353 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4354 tcpcheck->string = strdup(args[cur_arg + 1]);
4355 tcpcheck->expect_regex = NULL;
4356 tcpcheck->inverse = inverse;
4357
4358 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4359 }
4360 else if (strcmp(ptr_arg, "rstring") == 0) {
4361 if (!*(args[cur_arg + 1])) {
4362 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4363 file, linenum, args[0], args[1], ptr_arg);
4364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367 struct tcpcheck_rule *tcpcheck;
4368
4369 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4370
4371 tcpcheck->action = TCPCHK_ACT_EXPECT;
4372 tcpcheck->string_len = 0;
4373 tcpcheck->string = NULL;
4374 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4375 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4376 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4377 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
4381 tcpcheck->inverse = inverse;
4382
4383 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4384 }
4385 else {
4386 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4387 file, linenum, args[0], args[1], ptr_arg);
4388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
4390 }
4391 }
4392 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004393 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
4397 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004398 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004399 if (curproxy == &defproxy) {
4400 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004403 }
4404
Willy Tarreaub80c2302007-11-30 20:51:32 +01004405 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004407
4408 if (strcmp(args[1], "fail") == 0) {
4409 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004410 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004411 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4412 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004415 }
4416
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004417 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4418 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4419 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004422 }
4423 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4424 }
4425 else {
4426 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004429 }
4430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431#ifdef TPROXY
4432 else if (!strcmp(args[0], "transparent")) {
4433 /* enable transparent proxy connections */
4434 curproxy->options |= PR_O_TRANSP;
4435 }
4436#endif
4437 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004438 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004440
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 if (*(args[1]) == 0) {
4442 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
4446 curproxy->maxconn = atol(args[1]);
4447 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004448 else if (!strcmp(args[0], "backlog")) { /* backlog */
4449 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004451
4452 if (*(args[1]) == 0) {
4453 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004456 }
4457 curproxy->backlog = atol(args[1]);
4458 }
Willy Tarreau86034312006-12-29 00:10:33 +01004459 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004460 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004461 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004462
Willy Tarreau86034312006-12-29 00:10:33 +01004463 if (*(args[1]) == 0) {
4464 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004467 }
4468 curproxy->fullconn = atol(args[1]);
4469 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004470 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4471 if (*(args[1]) == 0) {
4472 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004476 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4477 if (err) {
4478 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4479 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004482 }
4483 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
4485 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004486 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004487 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004488 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004489
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 if (curproxy == &defproxy) {
4491 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004495 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004497
Willy Tarreau902636f2013-03-10 19:44:48 +01004498 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004499 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004500 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004501 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004502 goto out;
4503 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004504
4505 proto = protocol_by_family(sk->ss_family);
4506 if (!proto || !proto->connect) {
4507 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4508 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004509 err_code |= ERR_ALERT | ERR_FATAL;
4510 goto out;
4511 }
4512
4513 if (port1 != port2) {
4514 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4515 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004519
4520 if (!port1) {
4521 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4522 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004523 err_code |= ERR_ALERT | ERR_FATAL;
4524 goto out;
4525 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004526
Willy Tarreaud5191e72010-02-09 20:50:45 +01004527 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004528 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004529 }
4530 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004533
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004534 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4535 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004540 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004541 /**
4542 * The syntax for hash-type config element is
4543 * hash-type {map-based|consistent} [[<algo>] avalanche]
4544 *
4545 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4546 */
4547 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004548
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004549 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4550 err_code |= ERR_WARN;
4551
4552 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004553 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4554 }
4555 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004556 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4557 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004558 else if (strcmp(args[1], "avalanche") == 0) {
4559 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]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004562 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004563 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004564 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
Bhaskar98634f02013-10-29 23:30:51 -04004568
4569 /* set the hash function to use */
4570 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004571 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004572 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004573
4574 /* if consistent with no argument, then avalanche modifier is also applied */
4575 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4576 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004577 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004578 /* set the hash function */
4579 if (!strcmp(args[2], "sdbm")) {
4580 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4581 }
4582 else if (!strcmp(args[2], "djb2")) {
4583 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004584 } else if (!strcmp(args[2], "wt6")) {
4585 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004586 }
4587 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004588 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
4591 }
4592
4593 /* set the hash modifier */
4594 if (!strcmp(args[3], "avalanche")) {
4595 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4596 }
4597 else if (*args[3]) {
4598 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004602 }
William Lallemanda73203e2012-03-12 12:48:57 +01004603 }
William Lallemanda73203e2012-03-12 12:48:57 +01004604 else if (strcmp(args[0], "unique-id-format") == 0) {
4605 if (!*(args[1])) {
4606 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
William Lallemand3203ff42012-11-11 17:30:56 +01004610 if (*(args[2])) {
4611 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004615 free(curproxy->conf.uniqueid_format_string);
4616 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004617
Willy Tarreau62a61232013-04-12 18:13:46 +02004618 free(curproxy->conf.uif_file);
4619 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4620 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004621 }
William Lallemanda73203e2012-03-12 12:48:57 +01004622
4623 else if (strcmp(args[0], "unique-id-header") == 0) {
4624 if (!*(args[1])) {
4625 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
4628 }
4629 free(curproxy->header_unique_id);
4630 curproxy->header_unique_id = strdup(args[1]);
4631 }
4632
William Lallemand723b73a2012-02-08 16:37:49 +01004633 else if (strcmp(args[0], "log-format") == 0) {
4634 if (!*(args[1])) {
4635 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
4638 }
William Lallemand3203ff42012-11-11 17:30:56 +01004639 if (*(args[2])) {
4640 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004644
Willy Tarreau62a61232013-04-12 18:13:46 +02004645 if (curproxy->conf.logformat_string != default_http_log_format &&
4646 curproxy->conf.logformat_string != default_tcp_log_format &&
4647 curproxy->conf.logformat_string != clf_http_log_format)
4648 free(curproxy->conf.logformat_string);
4649 curproxy->conf.logformat_string = strdup(args[1]);
4650
4651 free(curproxy->conf.lfs_file);
4652 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4653 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004654
4655 /* get a chance to improve log-format error reporting by
4656 * reporting the correct line-number when possible.
4657 */
4658 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4659 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4660 file, linenum, curproxy->id);
4661 err_code |= ERR_WARN;
4662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663 }
William Lallemand723b73a2012-02-08 16:37:49 +01004664
William Lallemand0f99e342011-10-12 17:50:54 +02004665 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4666 /* delete previous herited or defined syslog servers */
4667 struct logsrv *back;
4668
4669 if (*(args[1]) != 0) {
4670 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
4674
William Lallemand723b73a2012-02-08 16:37:49 +01004675 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4676 LIST_DEL(&tmplogsrv->list);
4677 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004678 }
4679 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004681 struct logsrv *logsrv;
4682
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004684 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004685 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004686 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004687 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004688 LIST_INIT(&node->list);
4689 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691 }
4692 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004693 struct sockaddr_storage *sk;
4694 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004695
4696 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697
William Lallemand0f99e342011-10-12 17:50:54 +02004698 logsrv->facility = get_log_facility(args[2]);
4699 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
4703
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
4705
William Lallemand0f99e342011-10-12 17:50:54 +02004706 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004708 logsrv->level = get_log_level(args[3]);
4709 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
4713
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 }
4715 }
4716
William Lallemand0f99e342011-10-12 17:50:54 +02004717 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004718 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004719 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004720 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004721 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004725 }
4726 }
4727
Willy Tarreau902636f2013-03-10 19:44:48 +01004728 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004729 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004730 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004731 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004732 goto out;
4733 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004734
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004735 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004736
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004737 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004738 if (port1 != port2) {
4739 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4740 file, linenum, args[0], args[1]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004745 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004746 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 }
William Lallemand0f99e342011-10-12 17:50:54 +02004748
4749 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 else {
4752 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4753 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 }
4758 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004759 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004760 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004761 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004762 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004763
Willy Tarreau977b8e42006-12-29 14:19:17 +01004764 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004766
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004768 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4769 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004773
4774 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004775 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4776 free(curproxy->conn_src.iface_name);
4777 curproxy->conn_src.iface_name = NULL;
4778 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004779
Willy Tarreau902636f2013-03-10 19:44:48 +01004780 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004781 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004782 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004783 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004784 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004785 goto out;
4786 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004787
4788 proto = protocol_by_family(sk->ss_family);
4789 if (!proto || !proto->connect) {
4790 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004791 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004795
4796 if (port1 != port2) {
4797 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4798 file, linenum, args[0], args[1]);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
4802
Willy Tarreauef9a3602012-12-08 22:29:20 +01004803 curproxy->conn_src.source_addr = *sk;
4804 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004805
4806 cur_arg = 2;
4807 while (*(args[cur_arg])) {
4808 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004809#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4810#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004811 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004812 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4813 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004816 }
4817#endif
4818 if (!*args[cur_arg + 1]) {
4819 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4820 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004823 }
4824
4825 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004826 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4827 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004829 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4830 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004831 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4832 char *name, *end;
4833
4834 name = args[cur_arg+1] + 7;
4835 while (isspace(*name))
4836 name++;
4837
4838 end = name;
4839 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4840 end++;
4841
Willy Tarreauef9a3602012-12-08 22:29:20 +01004842 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4843 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4844 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4845 curproxy->conn_src.bind_hdr_len = end - name;
4846 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4847 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4848 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004849
4850 /* now look for an occurrence number */
4851 while (isspace(*end))
4852 end++;
4853 if (*end == ',') {
4854 end++;
4855 name = end;
4856 if (*end == '-')
4857 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004858 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004859 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004860 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004861 }
4862
Willy Tarreauef9a3602012-12-08 22:29:20 +01004863 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004864 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4865 " occurrences values smaller than %d.\n",
4866 file, linenum, MAX_HDR_HISTORY);
4867 err_code |= ERR_ALERT | ERR_FATAL;
4868 goto out;
4869 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004871 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004872
Willy Tarreau902636f2013-03-10 19:44:48 +01004873 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004874 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004875 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004876 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004877 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004878 goto out;
4879 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004880
4881 proto = protocol_by_family(sk->ss_family);
4882 if (!proto || !proto->connect) {
4883 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4884 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004888
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004889 if (port1 != port2) {
4890 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4891 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004895 curproxy->conn_src.tproxy_addr = *sk;
4896 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004897 }
4898 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004899#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004900 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004901#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902#else /* no TPROXY support */
4903 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004904 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004907#endif
4908 cur_arg += 2;
4909 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004910 }
4911
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004912 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4913#ifdef SO_BINDTODEVICE
4914 if (!*args[cur_arg + 1]) {
4915 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004919 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004920 free(curproxy->conn_src.iface_name);
4921 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4922 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923 global.last_checks |= LSTCHK_NETADM;
4924#else
4925 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4926 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004929#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004930 cur_arg += 2;
4931 continue;
4932 }
4933 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004934 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004939 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4940 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4941 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952
4953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004954 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004968 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004987 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004993 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004994 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005000
5001 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5002 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005003 }
5004 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005006 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005007 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005009 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005010
5011 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5012 Warning("parsing [%s:%d] : The '%s' directive is now deprecated in favor of the more efficient 'use_backend' which uses a different but more powerful syntax. Future versions will not support '%s' anymore, you should convert it now!\n", file, linenum, args[0], args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01005013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5017 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021
5022 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005023 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005024 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
5028 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005030 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005031 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 }
5035 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005037 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005038 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
5042 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005044 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005045 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
5049 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005051 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005052 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005056 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005058 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005059 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005060 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005061 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005064 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005065
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 if (curproxy == &defproxy) {
5067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005071 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 if (*(args[1]) == 0) {
5075 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005079
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005080 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005081 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5082 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5083 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
5086 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005087 err_code |= warnif_cond_conflicts(cond,
5088 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5089 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005090 }
5091 else if (*args[2]) {
5092 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5093 file, linenum, args[0], args[2]);
5094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
5096 }
5097
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005098 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005099 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005100 wl->s = strdup(args[1]);
5101 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005102 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5107 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005111
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005113 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005114 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
5118 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005120 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005121 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005122 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005127 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005128 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005129 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
5132 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5135 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
5139
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005141 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005142 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
5146 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
5153 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005155 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005156 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005161 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005162
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 if (curproxy == &defproxy) {
5164 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005168 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005170
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 if (*(args[1]) == 0) {
5172 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
5176
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005177 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005178 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5179 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5180 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005184 err_code |= warnif_cond_conflicts(cond,
5185 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5186 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005187 }
5188 else if (*args[2]) {
5189 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5190 file, linenum, args[0], args[2]);
5191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
5193 }
5194
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005195 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005196 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005197 wl->s = strdup(args[1]);
5198 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
5200 else if (!strcmp(args[0], "errorloc") ||
5201 !strcmp(args[0], "errorloc302") ||
5202 !strcmp(args[0], "errorloc303")) { /* error location */
5203 int errnum, errlen;
5204 char *err;
5205
Willy Tarreau977b8e42006-12-29 14:19:17 +01005206 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005208
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005210 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
5214
5215 errnum = atol(args[1]);
5216 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005217 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5218 err = malloc(errlen);
5219 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005221 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5222 err = malloc(errlen);
5223 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
5225
Willy Tarreau0f772532006-12-23 20:51:41 +01005226 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5227 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005228 chunk_destroy(&curproxy->errmsg[rc]);
5229 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005230 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005233
5234 if (rc >= HTTP_ERR_SIZE) {
5235 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5236 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 free(err);
5238 }
5239 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005240 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5241 int errnum, errlen, fd;
5242 char *err;
5243 struct stat stat;
5244
5245 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005246 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005247
5248 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005249 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252 }
5253
5254 fd = open(args[2], O_RDONLY);
5255 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5256 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5257 file, linenum, args[2], args[1]);
5258 if (fd >= 0)
5259 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005262 }
5263
Willy Tarreau27a674e2009-08-17 07:23:33 +02005264 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005265 errlen = stat.st_size;
5266 } else {
5267 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005268 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005270 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005271 }
5272
5273 err = malloc(errlen); /* malloc() must succeed during parsing */
5274 errnum = read(fd, err, errlen);
5275 if (errnum != errlen) {
5276 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5277 file, linenum, args[2], args[1]);
5278 close(fd);
5279 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005282 }
5283 close(fd);
5284
5285 errnum = atol(args[1]);
5286 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5287 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005288 chunk_destroy(&curproxy->errmsg[rc]);
5289 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005290 break;
5291 }
5292 }
5293
5294 if (rc >= HTTP_ERR_SIZE) {
5295 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5296 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005298 free(err);
5299 }
5300 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005301 else if (!strcmp(args[0], "compression")) {
5302 struct comp *comp;
5303 if (curproxy->comp == NULL) {
5304 comp = calloc(1, sizeof(struct comp));
5305 curproxy->comp = comp;
5306 } else {
5307 comp = curproxy->comp;
5308 }
5309
5310 if (!strcmp(args[1], "algo")) {
5311 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005312 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005313
William Lallemand82fe75c2012-10-23 10:25:10 +02005314 cur_arg = 2;
5315 if (!*args[cur_arg]) {
5316 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5317 file, linenum, args[0]);
5318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321 while (*(args[cur_arg])) {
5322 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5323 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5324 file, linenum, args[0], args[cur_arg]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
William Lallemand552df672012-11-07 13:21:47 +01005328 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5329 curproxy->comp->algos->end(&ctx);
5330 } else {
5331 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5332 file, linenum, args[0], args[cur_arg]);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005336 cur_arg ++;
5337 continue;
5338 }
5339 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005340 else if (!strcmp(args[1], "offload")) {
5341 comp->offload = 1;
5342 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005343 else if (!strcmp(args[1], "type")) {
5344 int cur_arg;
5345 cur_arg = 2;
5346 if (!*args[cur_arg]) {
5347 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5348 file, linenum, args[0]);
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352 while (*(args[cur_arg])) {
5353 comp_append_type(comp, args[cur_arg]);
5354 cur_arg ++;
5355 continue;
5356 }
5357 }
5358 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005359 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005360 file, linenum, args[0]);
5361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
5363 }
5364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005366 struct cfg_kw_list *kwl;
5367 int index;
5368
5369 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5370 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5371 if (kwl->kw[index].section != CFG_LISTEN)
5372 continue;
5373 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5374 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005375 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005376 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005377 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005380 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005381 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005382 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_WARN;
5384 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005385 }
Willy Tarreau93893792009-07-23 13:19:11 +02005386 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005387 }
5388 }
5389 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005390
Willy Tarreau6daf3432008-01-22 16:44:08 +01005391 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 }
Willy Tarreau93893792009-07-23 13:19:11 +02005395 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005396 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005397 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398}
5399
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005400int
5401cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5402{
5403
5404 int err_code = 0;
5405 const char *err;
5406
5407 if (!strcmp(args[0], "userlist")) { /* new userlist */
5408 struct userlist *newul;
5409
5410 if (!*args[1]) {
5411 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5412 file, linenum, args[0]);
5413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
5415 }
5416
5417 err = invalid_char(args[1]);
5418 if (err) {
5419 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5420 file, linenum, *err, args[0], args[1]);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424
5425 for (newul = userlist; newul; newul = newul->next)
5426 if (!strcmp(newul->name, args[1])) {
5427 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5428 file, linenum, args[1]);
5429 err_code |= ERR_WARN;
5430 goto out;
5431 }
5432
5433 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5434 if (!newul) {
5435 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5436 err_code |= ERR_ALERT | ERR_ABORT;
5437 goto out;
5438 }
5439
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005440 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005441 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005442 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5443 err_code |= ERR_ALERT | ERR_ABORT;
5444 goto out;
5445 }
5446
5447 newul->next = userlist;
5448 userlist = newul;
5449
5450 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005451 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005452 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005453 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005454
5455 if (!*args[1]) {
5456 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5457 file, linenum, args[0]);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
5461
5462 err = invalid_char(args[1]);
5463 if (err) {
5464 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5465 file, linenum, *err, args[0], args[1]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
5469
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005470 for (ag = userlist->groups; ag; ag = ag->next)
5471 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005472 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5473 file, linenum, args[1], userlist->name);
5474 err_code |= ERR_ALERT;
5475 goto out;
5476 }
5477
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005478 ag = calloc(1, sizeof(*ag));
5479 if (!ag) {
5480 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5481 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 goto out;
5483 }
5484
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005485 ag->name = strdup(args[1]);
5486 if (!ag) {
5487 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5488 err_code |= ERR_ALERT | ERR_ABORT;
5489 goto out;
5490 }
5491
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005492 cur_arg = 2;
5493
5494 while (*args[cur_arg]) {
5495 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005496 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005497 cur_arg += 2;
5498 continue;
5499 } else {
5500 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5501 file, linenum, args[0]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
5505 }
5506
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005507 ag->next = userlist->groups;
5508 userlist->groups = ag;
5509
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005510 } else if (!strcmp(args[0], "user")) { /* new user */
5511 struct auth_users *newuser;
5512 int cur_arg;
5513
5514 if (!*args[1]) {
5515 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5516 file, linenum, args[0]);
5517 err_code |= ERR_ALERT | ERR_FATAL;
5518 goto out;
5519 }
5520
5521 for (newuser = userlist->users; newuser; newuser = newuser->next)
5522 if (!strcmp(newuser->user, args[1])) {
5523 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5524 file, linenum, args[1], userlist->name);
5525 err_code |= ERR_ALERT;
5526 goto out;
5527 }
5528
5529 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5530 if (!newuser) {
5531 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5532 err_code |= ERR_ALERT | ERR_ABORT;
5533 goto out;
5534 }
5535
5536 newuser->user = strdup(args[1]);
5537
5538 newuser->next = userlist->users;
5539 userlist->users = newuser;
5540
5541 cur_arg = 2;
5542
5543 while (*args[cur_arg]) {
5544 if (!strcmp(args[cur_arg], "password")) {
5545#ifndef CONFIG_HAP_CRYPT
5546 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5547 file, linenum);
5548 err_code |= ERR_ALERT;
5549#endif
5550 newuser->pass = strdup(args[cur_arg + 1]);
5551 cur_arg += 2;
5552 continue;
5553 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5554 newuser->pass = strdup(args[cur_arg + 1]);
5555 newuser->flags |= AU_O_INSECURE;
5556 cur_arg += 2;
5557 continue;
5558 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005559 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005560 cur_arg += 2;
5561 continue;
5562 } else {
5563 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5564 file, linenum, args[0]);
5565 err_code |= ERR_ALERT | ERR_FATAL;
5566 goto out;
5567 }
5568 }
5569 } else {
5570 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 }
5573
5574out:
5575 return err_code;
5576}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577
5578/*
5579 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005580 * Returns the error code, 0 if OK, or any combination of :
5581 * - ERR_ABORT: must abort ASAP
5582 * - ERR_FATAL: we can continue parsing but not start the service
5583 * - ERR_WARN: a warning has been emitted
5584 * - ERR_ALERT: an alert has been emitted
5585 * Only the two first ones can stop processing, the two others are just
5586 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005588int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005590 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 FILE *f;
5592 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005593 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005594 struct cfg_section *cs = NULL;
5595 struct cfg_section *ics;
5596
5597 /* Register internal sections */
5598 if (!cfg_register_section("listen", cfg_parse_listen) ||
5599 !cfg_register_section("frontend", cfg_parse_listen) ||
5600 !cfg_register_section("backend", cfg_parse_listen) ||
5601 !cfg_register_section("ruleset", cfg_parse_listen) ||
5602 !cfg_register_section("defaults", cfg_parse_listen) ||
5603 !cfg_register_section("global", cfg_parse_global) ||
5604 !cfg_register_section("userlist", cfg_parse_users) ||
5605 !cfg_register_section("peers", cfg_parse_peers))
5606 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 if ((f=fopen(file,"r")) == NULL)
5609 return -1;
5610
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005611 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005612 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005613 char *end;
5614 char *args[MAX_LINE_ARGS + 1];
5615 char *line = thisline;
5616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 linenum++;
5618
5619 end = line + strlen(line);
5620
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005621 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5622 /* Check if we reached the limit and the last char is not \n.
5623 * Watch out for the last line without the terminating '\n'!
5624 */
5625 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005626 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005627 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005628 }
5629
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005631 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 line++;
5633
5634 arg = 0;
5635 args[arg] = line;
5636
5637 while (*line && arg < MAX_LINE_ARGS) {
5638 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5639 * C equivalent value. Other combinations left unchanged (eg: \1).
5640 */
5641 if (*line == '\\') {
5642 int skip = 0;
5643 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5644 *line = line[1];
5645 skip = 1;
5646 }
5647 else if (line[1] == 'r') {
5648 *line = '\r';
5649 skip = 1;
5650 }
5651 else if (line[1] == 'n') {
5652 *line = '\n';
5653 skip = 1;
5654 }
5655 else if (line[1] == 't') {
5656 *line = '\t';
5657 skip = 1;
5658 }
5659 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005660 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 unsigned char hex1, hex2;
5662 hex1 = toupper(line[2]) - '0';
5663 hex2 = toupper(line[3]) - '0';
5664 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5665 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5666 *line = (hex1<<4) + hex2;
5667 skip = 3;
5668 }
5669 else {
5670 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 }
5673 }
5674 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005675 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 end -= skip;
5677 }
5678 line++;
5679 }
5680 else if (*line == '#' || *line == '\n' || *line == '\r') {
5681 /* end of string, end of loop */
5682 *line = 0;
5683 break;
5684 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005685 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005687 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005688 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 line++;
5690 args[++arg] = line;
5691 }
5692 else {
5693 line++;
5694 }
5695 }
5696
5697 /* empty line */
5698 if (!**args)
5699 continue;
5700
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005701 if (*line) {
5702 /* we had to stop due to too many args.
5703 * Let's terminate the string, print the offending part then cut the
5704 * last arg.
5705 */
5706 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5707 line++;
5708 *line = '\0';
5709
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005710 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005711 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 args[arg] = line;
5714 }
5715
Willy Tarreau540abe42007-05-02 20:50:16 +02005716 /* zero out remaining args and ensure that at least one entry
5717 * is zeroed out.
5718 */
5719 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 args[arg] = line;
5721 }
5722
Willy Tarreau3842f002009-06-14 11:39:52 +02005723 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005724 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005725 char *tmp;
5726
Willy Tarreau3842f002009-06-14 11:39:52 +02005727 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005728 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005729 for (arg=0; *args[arg+1]; arg++)
5730 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005731 *tmp = '\0'; // fix the next arg to \0
5732 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005733 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005734 else if (!strcmp(args[0], "default")) {
5735 kwm = KWM_DEF;
5736 for (arg=0; *args[arg+1]; arg++)
5737 args[arg] = args[arg+1]; // shift args after inversion
5738 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005739
William Lallemand0f99e342011-10-12 17:50:54 +02005740 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5741 strcmp(args[0], "log") != 0) {
5742 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005743 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005744 }
5745
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005746 /* detect section start */
5747 list_for_each_entry(ics, &sections, list) {
5748 if (strcmp(args[0], ics->section_name) == 0) {
5749 cursection = ics->section_name;
5750 cs = ics;
5751 break;
5752 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005753 }
5754
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005756 if (cs)
5757 err_code |= cs->section_parser(file, linenum, args, kwm);
5758 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005759 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005760 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005762
5763 if (err_code & ERR_ABORT)
5764 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005766 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005768 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005769}
5770
Willy Tarreaubb925012009-07-23 13:36:36 +02005771/*
5772 * Returns the error code, 0 if OK, or any combination of :
5773 * - ERR_ABORT: must abort ASAP
5774 * - ERR_FATAL: we can continue parsing but not start the service
5775 * - ERR_WARN: a warning has been emitted
5776 * - ERR_ALERT: an alert has been emitted
5777 * Only the two first ones can stop processing, the two others are just
5778 * indicators.
5779 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005780int check_config_validity()
5781{
5782 int cfgerr = 0;
5783 struct proxy *curproxy = NULL;
5784 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005785 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005786 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005787 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005789 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 /*
5791 * Now, check for the integrity of all that we have collected.
5792 */
5793
5794 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005795 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796
Willy Tarreau193b8c62012-11-22 00:17:38 +01005797 if (!global.tune.max_http_hdr)
5798 global.tune.max_http_hdr = MAX_HTTP_HDR;
5799
5800 if (!global.tune.cookie_len)
5801 global.tune.cookie_len = CAPTURE_LEN;
5802
5803 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5804
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005805 /* Post initialisation of the users and groups lists. */
5806 err_code = userlist_postinit();
5807 if (err_code != ERR_NONE)
5808 goto out;
5809
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005810 /* first, we will invert the proxy list order */
5811 curproxy = NULL;
5812 while (proxy) {
5813 struct proxy *next;
5814
5815 next = proxy->next;
5816 proxy->next = curproxy;
5817 curproxy = proxy;
5818 if (!next)
5819 break;
5820 proxy = next;
5821 }
5822
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005824 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005825 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005826 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005827 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005828 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005829 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005830 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005831
Willy Tarreau050536d2012-10-04 08:47:34 +02005832 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005833 /* proxy ID not set, use automatic numbering with first
5834 * spare entry starting with next_pxid.
5835 */
5836 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5837 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5838 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005839 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005840 next_pxid++;
5841
Willy Tarreau55ea7572007-06-17 19:56:27 +02005842
Willy Tarreaubaaee002006-06-26 02:48:02 +02005843 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005844 /* ensure we don't keep listeners uselessly bound */
5845 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 curproxy = curproxy->next;
5847 continue;
5848 }
5849
Willy Tarreau16a21472012-11-19 12:39:59 +01005850 /* number of processes this proxy is bound to */
5851 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5852
Willy Tarreauff01a212009-03-15 13:46:16 +01005853 switch (curproxy->mode) {
5854 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005855 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005856 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005857 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5858 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005859 cfgerr++;
5860 }
5861
5862 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005863 Warning("config : servers will be ignored for %s '%s'.\n",
5864 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005865 break;
5866
5867 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005868 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005869 break;
5870
5871 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005872 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005873 break;
5874 }
5875
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005876 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005877 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005878 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5880 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005881 cfgerr++;
5882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005884 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005885 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5886 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005887 cfgerr++;
5888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005890 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005891 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5892 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005893 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005894 }
5895 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005896 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005897 /* If no LB algo is set in a backend, and we're not in
5898 * transparent mode, dispatch mode nor proxy mode, we
5899 * want to use balance roundrobin by default.
5900 */
5901 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5902 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 }
5904 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005905
Willy Tarreau1620ec32011-08-06 17:05:02 +02005906 if (curproxy->options & PR_O_DISPATCH)
5907 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5908 else if (curproxy->options & PR_O_HTTP_PROXY)
5909 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5910 else if (curproxy->options & PR_O_TRANSP)
5911 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005912
Willy Tarreau1620ec32011-08-06 17:05:02 +02005913 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5914 if (curproxy->options & PR_O_DISABLE404) {
5915 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5916 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5917 err_code |= ERR_WARN;
5918 curproxy->options &= ~PR_O_DISABLE404;
5919 }
5920 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5921 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5922 "send-state", proxy_type_str(curproxy), curproxy->id);
5923 err_code |= ERR_WARN;
5924 curproxy->options &= ~PR_O2_CHK_SNDST;
5925 }
Willy Tarreauef781042010-01-27 11:53:01 +01005926 }
5927
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005928 /* if a default backend was specified, let's find it */
5929 if (curproxy->defbe.name) {
5930 struct proxy *target;
5931
Alex Williams96532db2009-11-01 21:27:13 -05005932 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005933 if (!target) {
5934 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5935 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005936 cfgerr++;
5937 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005938 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5939 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005940 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005941 } else {
5942 free(curproxy->defbe.name);
5943 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005944 /* we force the backend to be present on at least all of
5945 * the frontend's processes.
5946 */
5947 target->bind_proc = curproxy->bind_proc ?
5948 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005949
5950 /* Emit a warning if this proxy also has some servers */
5951 if (curproxy->srv) {
5952 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5953 curproxy->id);
5954 err_code |= ERR_WARN;
5955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005956 }
5957 }
5958
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005959 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005960 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5961 /* map jump target for ACT_SETBE in req_rep chain */
5962 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005963 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005964 struct proxy *target;
5965
Willy Tarreaua496b602006-12-17 23:15:24 +01005966 if (exp->action != ACT_SETBE)
5967 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005968
Alex Williams96532db2009-11-01 21:27:13 -05005969 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005970 if (!target) {
5971 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5972 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005973 cfgerr++;
5974 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005975 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5976 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005977 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005978 } else {
5979 free((void *)exp->replace);
5980 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005981 /* we force the backend to be present on at least all of
5982 * the frontend's processes.
5983 */
5984 target->bind_proc = curproxy->bind_proc ?
5985 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005986 }
5987 }
5988 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005989
5990 /* find the target proxy for 'use_backend' rules */
5991 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005992 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005993 struct logformat_node *node;
5994 char *pxname;
5995
5996 /* Try to parse the string as a log format expression. If the result
5997 * of the parsing is only one entry containing a simple string, then
5998 * it's a standard string corresponding to a static rule, thus the
5999 * parsing is cancelled and be.name is restored to be resolved.
6000 */
6001 pxname = rule->be.name;
6002 LIST_INIT(&rule->be.expr);
6003 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6004 curproxy->conf.args.file, curproxy->conf.args.line);
6005 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6006
6007 if (!LIST_ISEMPTY(&rule->be.expr)) {
6008 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6009 rule->dynamic = 1;
6010 free(pxname);
6011 continue;
6012 }
6013 /* simple string: free the expression and fall back to static rule */
6014 free(node->arg);
6015 free(node);
6016 }
6017
6018 rule->dynamic = 0;
6019 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006020
Alex Williams96532db2009-11-01 21:27:13 -05006021 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006022
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006023 if (!target) {
6024 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6025 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006026 cfgerr++;
6027 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006028 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6029 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006030 cfgerr++;
6031 } else {
6032 free((void *)rule->be.name);
6033 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006034 /* we force the backend to be present on at least all of
6035 * the frontend's processes.
6036 */
6037 target->bind_proc = curproxy->bind_proc ?
6038 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006039 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006040 }
6041
6042 /* find the target proxy for 'use_backend' rules */
6043 list_for_each_entry(srule, &curproxy->server_rules, list) {
6044 struct server *target = findserver(curproxy, srule->srv.name);
6045
6046 if (!target) {
6047 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6048 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6049 cfgerr++;
6050 continue;
6051 }
6052 free((void *)srule->srv.name);
6053 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006054 }
6055
Emeric Brunb982a3d2010-01-04 15:45:53 +01006056 /* find the target table for 'stick' rules */
6057 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6058 struct proxy *target;
6059
Emeric Brun1d33b292010-01-04 15:47:17 +01006060 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6061 if (mrule->flags & STK_IS_STORE)
6062 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6063
Emeric Brunb982a3d2010-01-04 15:45:53 +01006064 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006065 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006066 else
6067 target = curproxy;
6068
6069 if (!target) {
6070 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6071 curproxy->id, mrule->table.name);
6072 cfgerr++;
6073 }
6074 else if (target->table.size == 0) {
6075 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6076 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6077 cfgerr++;
6078 }
Willy Tarreau12785782012-04-27 21:37:17 +02006079 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6080 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006081 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6082 cfgerr++;
6083 }
6084 else {
6085 free((void *)mrule->table.name);
6086 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006087 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006088 }
6089 }
6090
6091 /* find the target table for 'store response' rules */
6092 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6093 struct proxy *target;
6094
Emeric Brun1d33b292010-01-04 15:47:17 +01006095 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6096
Emeric Brunb982a3d2010-01-04 15:45:53 +01006097 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006098 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006099 else
6100 target = curproxy;
6101
6102 if (!target) {
6103 Alert("Proxy '%s': unable to find store table '%s'.\n",
6104 curproxy->id, mrule->table.name);
6105 cfgerr++;
6106 }
6107 else if (target->table.size == 0) {
6108 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6109 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6110 cfgerr++;
6111 }
Willy Tarreau12785782012-04-27 21:37:17 +02006112 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6113 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006114 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6115 cfgerr++;
6116 }
6117 else {
6118 free((void *)mrule->table.name);
6119 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006120 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006121 }
6122 }
6123
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006124 /* find the target table for 'tcp-request' layer 4 rules */
6125 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6126 struct proxy *target;
6127
Willy Tarreaub4c84932013-07-23 19:15:30 +02006128 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006129 continue;
6130
6131 if (trule->act_prm.trk_ctr.table.n)
6132 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6133 else
6134 target = curproxy;
6135
6136 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006137 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6138 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006139 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006140 cfgerr++;
6141 }
6142 else if (target->table.size == 0) {
6143 Alert("Proxy '%s': table '%s' used but not configured.\n",
6144 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6145 cfgerr++;
6146 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006147 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6148 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6149 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006150 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006151 cfgerr++;
6152 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006153 else {
6154 free(trule->act_prm.trk_ctr.table.n);
6155 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006156 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006157 * to pass a list of counters to track and allocate them right here using
6158 * stktable_alloc_data_type().
6159 */
6160 }
6161 }
6162
Willy Tarreaud1f96522010-08-03 19:34:32 +02006163 /* find the target table for 'tcp-request' layer 6 rules */
6164 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6165 struct proxy *target;
6166
Willy Tarreaub4c84932013-07-23 19:15:30 +02006167 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006168 continue;
6169
6170 if (trule->act_prm.trk_ctr.table.n)
6171 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6172 else
6173 target = curproxy;
6174
6175 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006176 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6177 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006178 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006179 cfgerr++;
6180 }
6181 else if (target->table.size == 0) {
6182 Alert("Proxy '%s': table '%s' used but not configured.\n",
6183 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6184 cfgerr++;
6185 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006186 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6187 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6188 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006189 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006190 cfgerr++;
6191 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006192 else {
6193 free(trule->act_prm.trk_ctr.table.n);
6194 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006195 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006196 * to pass a list of counters to track and allocate them right here using
6197 * stktable_alloc_data_type().
6198 */
6199 }
6200 }
6201
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006202 /* move any "block" rules at the beginning of the http-request rules */
6203 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6204 /* insert block_rules into http_req_rules at the beginning */
6205 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6206 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6207 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6208 curproxy->http_req_rules.n = curproxy->block_rules.n;
6209 LIST_INIT(&curproxy->block_rules);
6210 }
6211
Emeric Brun32da3c42010-09-23 18:39:19 +02006212 if (curproxy->table.peers.name) {
6213 struct peers *curpeers = peers;
6214
6215 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6216 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6217 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006218 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006219 break;
6220 }
6221 }
6222
6223 if (!curpeers) {
6224 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6225 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006226 free((void *)curproxy->table.peers.name);
6227 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006228 cfgerr++;
6229 }
6230 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006231 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6232 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006233 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006234 cfgerr++;
6235 }
6236 }
6237
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006238 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006239 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006240 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6241 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6242 "proxy", curproxy->id);
6243 cfgerr++;
6244 goto out_uri_auth_compat;
6245 }
6246
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006247 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006248 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006249 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006250 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006251
Willy Tarreau95fa4692010-02-01 13:05:50 +01006252 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6253 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006254
6255 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006256 uri_auth_compat_req[i++] = "realm";
6257 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6258 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006259
Willy Tarreau95fa4692010-02-01 13:05:50 +01006260 uri_auth_compat_req[i++] = "unless";
6261 uri_auth_compat_req[i++] = "{";
6262 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6263 uri_auth_compat_req[i++] = "}";
6264 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006265
Willy Tarreauff011f22011-01-06 17:51:27 +01006266 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6267 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006268 cfgerr++;
6269 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006270 }
6271
Willy Tarreauff011f22011-01-06 17:51:27 +01006272 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006273
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006274 if (curproxy->uri_auth->auth_realm) {
6275 free(curproxy->uri_auth->auth_realm);
6276 curproxy->uri_auth->auth_realm = NULL;
6277 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006278
6279 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006280 }
6281out_uri_auth_compat:
6282
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006283 /* compile the log format */
6284 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006285 if (curproxy->conf.logformat_string != default_http_log_format &&
6286 curproxy->conf.logformat_string != default_tcp_log_format &&
6287 curproxy->conf.logformat_string != clf_http_log_format)
6288 free(curproxy->conf.logformat_string);
6289 curproxy->conf.logformat_string = NULL;
6290 free(curproxy->conf.lfs_file);
6291 curproxy->conf.lfs_file = NULL;
6292 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006293 }
6294
Willy Tarreau62a61232013-04-12 18:13:46 +02006295 if (curproxy->conf.logformat_string) {
6296 curproxy->conf.args.ctx = ARGC_LOG;
6297 curproxy->conf.args.file = curproxy->conf.lfs_file;
6298 curproxy->conf.args.line = curproxy->conf.lfs_line;
6299 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006300 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006301 curproxy->conf.args.file = NULL;
6302 curproxy->conf.args.line = 0;
6303 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006304
Willy Tarreau62a61232013-04-12 18:13:46 +02006305 if (curproxy->conf.uniqueid_format_string) {
6306 curproxy->conf.args.ctx = ARGC_UIF;
6307 curproxy->conf.args.file = curproxy->conf.uif_file;
6308 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006309 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006310 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6311 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006312 curproxy->conf.args.file = NULL;
6313 curproxy->conf.args.line = 0;
6314 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006315
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006316 /* only now we can check if some args remain unresolved.
6317 * This must be done after the users and groups resolution.
6318 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006319 cfgerr += smp_resolve_args(curproxy);
6320 if (!cfgerr)
6321 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006322
Willy Tarreau2738a142006-07-08 17:28:09 +02006323 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006324 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006325 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006326 (!curproxy->timeout.connect ||
6327 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006328 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006329 " | While not properly invalid, you will certainly encounter various problems\n"
6330 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006331 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006332 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006333 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006334 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006335
Willy Tarreau1fa31262007-12-03 00:36:16 +01006336 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6337 * We must still support older configurations, so let's find out whether those
6338 * parameters have been set or must be copied from contimeouts.
6339 */
6340 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006341 if (!curproxy->timeout.tarpit ||
6342 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006343 /* tarpit timeout not set. We search in the following order:
6344 * default.tarpit, curr.connect, default.connect.
6345 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006346 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006347 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006348 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006349 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006350 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006351 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006352 }
6353 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006354 (!curproxy->timeout.queue ||
6355 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006356 /* queue timeout not set. We search in the following order:
6357 * default.queue, curr.connect, default.connect.
6358 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006359 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006360 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006361 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006362 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006363 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006364 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006365 }
6366 }
6367
Willy Tarreau1620ec32011-08-06 17:05:02 +02006368 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006369 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6370 curproxy->check_req = (char *)malloc(curproxy->check_len);
6371 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006372 }
6373
Willy Tarreau193b8c62012-11-22 00:17:38 +01006374 /* ensure that cookie capture length is not too large */
6375 if (curproxy->capture_len >= global.tune.cookie_len) {
6376 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6377 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6378 err_code |= ERR_WARN;
6379 curproxy->capture_len = global.tune.cookie_len - 1;
6380 }
6381
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006382 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006383 if (curproxy->nb_req_cap) {
6384 if (curproxy->mode == PR_MODE_HTTP) {
6385 curproxy->req_cap_pool = create_pool("ptrcap",
6386 curproxy->nb_req_cap * sizeof(char *),
6387 MEM_F_SHARED);
6388 } else {
6389 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6390 proxy_type_str(curproxy), curproxy->id);
6391 err_code |= ERR_WARN;
6392 curproxy->to_log &= ~LW_REQHDR;
6393 curproxy->nb_req_cap = 0;
6394 }
6395 }
6396
6397 if (curproxy->nb_rsp_cap) {
6398 if (curproxy->mode == PR_MODE_HTTP) {
6399 curproxy->rsp_cap_pool = create_pool("ptrcap",
6400 curproxy->nb_rsp_cap * sizeof(char *),
6401 MEM_F_SHARED);
6402 } else {
6403 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6404 proxy_type_str(curproxy), curproxy->id);
6405 err_code |= ERR_WARN;
6406 curproxy->to_log &= ~LW_REQHDR;
6407 curproxy->nb_rsp_cap = 0;
6408 }
6409 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006410
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 /* first, we will invert the servers list order */
6412 newsrv = NULL;
6413 while (curproxy->srv) {
6414 struct server *next;
6415
6416 next = curproxy->srv->next;
6417 curproxy->srv->next = newsrv;
6418 newsrv = curproxy->srv;
6419 if (!next)
6420 break;
6421 curproxy->srv = next;
6422 }
6423
Willy Tarreau17edc812014-01-03 12:14:34 +01006424 /* Check that no server name conflicts. This causes trouble in the stats.
6425 * We only emit a warning for the first conflict affecting each server,
6426 * in order to avoid combinatory explosion if all servers have the same
6427 * name. We do that only for servers which do not have an explicit ID,
6428 * because these IDs were made also for distinguishing them and we don't
6429 * want to annoy people who correctly manage them.
6430 */
6431 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6432 struct server *other_srv;
6433
6434 if (newsrv->puid)
6435 continue;
6436
6437 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6438 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6439 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6440 newsrv->conf.file, newsrv->conf.line,
6441 proxy_type_str(curproxy), curproxy->id,
6442 newsrv->id, other_srv->conf.line);
6443 break;
6444 }
6445 }
6446 }
6447
Willy Tarreaudd701652010-05-25 23:03:02 +02006448 /* assign automatic UIDs to servers which don't have one yet */
6449 next_id = 1;
6450 newsrv = curproxy->srv;
6451 while (newsrv != NULL) {
6452 if (!newsrv->puid) {
6453 /* server ID not set, use automatic numbering with first
6454 * spare entry starting with next_svid.
6455 */
6456 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6457 newsrv->conf.id.key = newsrv->puid = next_id;
6458 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6459 }
6460 next_id++;
6461 newsrv = newsrv->next;
6462 }
6463
Willy Tarreau20697042007-11-15 23:26:18 +01006464 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006465 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466
Willy Tarreau62c3be22012-01-20 13:12:32 +01006467 /*
6468 * If this server supports a maxconn parameter, it needs a dedicated
6469 * tasks to fill the emptied slots when a connection leaves.
6470 * Also, resolve deferred tracking dependency if needed.
6471 */
6472 newsrv = curproxy->srv;
6473 while (newsrv != NULL) {
6474 if (newsrv->minconn > newsrv->maxconn) {
6475 /* Only 'minconn' was specified, or it was higher than or equal
6476 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6477 * this will avoid further useless expensive computations.
6478 */
6479 newsrv->maxconn = newsrv->minconn;
6480 } else if (newsrv->maxconn && !newsrv->minconn) {
6481 /* minconn was not specified, so we set it to maxconn */
6482 newsrv->minconn = newsrv->maxconn;
6483 }
6484
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006485#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006486 if (newsrv->use_ssl || newsrv->check.use_ssl)
6487 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006488#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006489
Willy Tarreau2f075e92013-12-03 11:11:34 +01006490 /* set the check type on the server */
6491 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6492
Willy Tarreau62c3be22012-01-20 13:12:32 +01006493 if (newsrv->trackit) {
6494 struct proxy *px;
6495 struct server *srv;
6496 char *pname, *sname;
6497
6498 pname = newsrv->trackit;
6499 sname = strrchr(pname, '/');
6500
6501 if (sname)
6502 *sname++ = '\0';
6503 else {
6504 sname = pname;
6505 pname = NULL;
6506 }
6507
6508 if (pname) {
6509 px = findproxy(pname, PR_CAP_BE);
6510 if (!px) {
6511 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6512 proxy_type_str(curproxy), curproxy->id,
6513 newsrv->id, pname);
6514 cfgerr++;
6515 goto next_srv;
6516 }
6517 } else
6518 px = curproxy;
6519
6520 srv = findserver(px, sname);
6521 if (!srv) {
6522 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6523 proxy_type_str(curproxy), curproxy->id,
6524 newsrv->id, sname);
6525 cfgerr++;
6526 goto next_srv;
6527 }
6528
Willy Tarreauff5ae352013-12-11 20:36:34 +01006529 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006530 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6531 "tracking as it does not have checks enabled.\n",
6532 proxy_type_str(curproxy), curproxy->id,
6533 newsrv->id, px->id, srv->id);
6534 cfgerr++;
6535 goto next_srv;
6536 }
6537
6538 if (curproxy != px &&
6539 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6540 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6541 "tracking: disable-on-404 option inconsistency.\n",
6542 proxy_type_str(curproxy), curproxy->id,
6543 newsrv->id, px->id, srv->id);
6544 cfgerr++;
6545 goto next_srv;
6546 }
6547
6548 /* if the other server is forced disabled, we have to do the same here */
6549 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006550 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006551 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006552 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006553 }
6554
6555 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006556 newsrv->tracknext = srv->trackers;
6557 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006558
6559 free(newsrv->trackit);
6560 newsrv->trackit = NULL;
6561 }
6562 next_srv:
6563 newsrv = newsrv->next;
6564 }
6565
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006566 /* We have to initialize the server lookup mechanism depending
6567 * on what LB algorithm was choosen.
6568 */
6569
6570 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6571 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6572 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006573 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6574 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6575 init_server_map(curproxy);
6576 } else {
6577 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6578 fwrr_init_server_groups(curproxy);
6579 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006580 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006581
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006582 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006583 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6584 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6585 fwlc_init_server_tree(curproxy);
6586 } else {
6587 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6588 fas_init_server_tree(curproxy);
6589 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006590 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006591
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006592 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006593 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6594 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6595 chash_init_server_tree(curproxy);
6596 } else {
6597 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6598 init_server_map(curproxy);
6599 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006600 break;
6601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602
6603 if (curproxy->options & PR_O_LOGASAP)
6604 curproxy->to_log &= ~LW_BYTES;
6605
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006606 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006607 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006608 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6609 proxy_type_str(curproxy), curproxy->id);
6610 err_code |= ERR_WARN;
6611 }
6612
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006613 if (curproxy->mode != PR_MODE_HTTP) {
6614 int optnum;
6615
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006616 if (curproxy->uri_auth) {
6617 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6618 proxy_type_str(curproxy), curproxy->id);
6619 err_code |= ERR_WARN;
6620 curproxy->uri_auth = NULL;
6621 }
6622
Willy Tarreau87cf5142011-08-19 22:57:24 +02006623 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006624 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6625 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6626 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006627 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006628 }
6629
6630 if (curproxy->options & PR_O_ORGTO) {
6631 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6632 "originalto", proxy_type_str(curproxy), curproxy->id);
6633 err_code |= ERR_WARN;
6634 curproxy->options &= ~PR_O_ORGTO;
6635 }
6636
6637 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6638 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6639 (curproxy->cap & cfg_opts[optnum].cap) &&
6640 (curproxy->options & cfg_opts[optnum].val)) {
6641 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6642 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6643 err_code |= ERR_WARN;
6644 curproxy->options &= ~cfg_opts[optnum].val;
6645 }
6646 }
6647
6648 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6649 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6650 (curproxy->cap & cfg_opts2[optnum].cap) &&
6651 (curproxy->options2 & cfg_opts2[optnum].val)) {
6652 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6653 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6654 err_code |= ERR_WARN;
6655 curproxy->options2 &= ~cfg_opts2[optnum].val;
6656 }
6657 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006658
Pieter Baauwd551fb52013-05-08 22:49:23 +02006659#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006660 if (curproxy->conn_src.bind_hdr_occ) {
6661 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006662 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006663 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006664 err_code |= ERR_WARN;
6665 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006666#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006667 }
6668
Willy Tarreaubaaee002006-06-26 02:48:02 +02006669 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006670 * ensure that we're not cross-dressing a TCP server into HTTP.
6671 */
6672 newsrv = curproxy->srv;
6673 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006674 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006675 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6676 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006677 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006678 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006679
Willy Tarreau0cec3312011-10-31 13:49:26 +01006680 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6681 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6682 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6683 err_code |= ERR_WARN;
6684 }
6685
Willy Tarreau82ffa392013-08-13 17:19:08 +02006686 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6687 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6688 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6689 err_code |= ERR_WARN;
6690 }
6691
Pieter Baauwd551fb52013-05-08 22:49:23 +02006692#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006693 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6694 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006695 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 +01006696 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006697 err_code |= ERR_WARN;
6698 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006699#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006700 newsrv = newsrv->next;
6701 }
6702
Willy Tarreauc1a21672009-08-16 22:37:44 +02006703 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006704 if (!curproxy->accept)
6705 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006706
Willy Tarreauc1a21672009-08-16 22:37:44 +02006707 if (curproxy->tcp_req.inspect_delay ||
6708 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006709 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006710
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006711 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006712 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006713 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006714 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006715
6716 /* both TCP and HTTP must check switching rules */
6717 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6718 }
6719
6720 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006721 if (curproxy->tcp_req.inspect_delay ||
6722 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6723 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6724
Emeric Brun97679e72010-09-23 17:56:44 +02006725 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6726 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6727
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006728 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006729 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006730 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006731 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006732
6733 /* If the backend does requires RDP cookie persistence, we have to
6734 * enable the corresponding analyser.
6735 */
6736 if (curproxy->options2 & PR_O2_RDPC_PRST)
6737 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6738 }
6739
Emeric Brunc52962f2012-11-15 18:28:02 +01006740#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006741 /* Configure SSL for each bind line.
6742 * Note: if configuration fails at some point, the ->ctx member
6743 * remains NULL so that listeners can later detach.
6744 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006745 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006746 if (!bind_conf->is_ssl) {
6747 if (bind_conf->default_ctx) {
6748 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6749 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6750 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006751 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006752 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006753 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006754 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006755 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006756 cfgerr++;
6757 continue;
6758 }
6759
Emeric Brun4b3091e2012-09-24 15:48:52 +02006760 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006761 Alert("Unable to allocate SSL session cache.\n");
6762 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006763 continue;
6764 }
6765
Emeric Brunfc0421f2012-09-07 17:30:07 +02006766 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006767 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006768 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006769#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006770
Willy Tarreaue6b98942007-10-29 01:09:36 +01006771 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006772 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006773 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006774 if (!listener->luid) {
6775 /* listener ID not set, use automatic numbering with first
6776 * spare entry starting with next_luid.
6777 */
6778 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6779 listener->conf.id.key = listener->luid = next_id;
6780 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006781 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006782 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006783
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006784 /* enable separate counters */
6785 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6786 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006787 if (!listener->name)
6788 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006789 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006790
Willy Tarreaue6b98942007-10-29 01:09:36 +01006791 if (curproxy->options & PR_O_TCP_NOLING)
6792 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006793 if (!listener->maxconn)
6794 listener->maxconn = curproxy->maxconn;
6795 if (!listener->backlog)
6796 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006797 if (!listener->maxaccept)
6798 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6799
6800 /* we want to have an optimal behaviour on single process mode to
6801 * maximize the work at once, but in multi-process we want to keep
6802 * some fairness between processes, so we target half of the max
6803 * number of events to be balanced over all the processes the proxy
6804 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6805 * used to disable the limit.
6806 */
6807 if (listener->maxaccept > 0) {
6808 if (nbproc > 1)
6809 listener->maxaccept = (listener->maxaccept + 1) / 2;
6810 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6811 }
6812
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006813 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006814 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006815 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006816 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006817
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006818 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6819 listener->options |= LI_O_TCP_RULES;
6820
Willy Tarreaude3041d2010-05-31 10:56:17 +02006821 if (curproxy->mon_mask.s_addr)
6822 listener->options |= LI_O_CHK_MONNET;
6823
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006824 /* smart accept mode is automatic in HTTP mode */
6825 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006826 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006827 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6828 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006829 }
6830
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006831 /* Release unused SSL configs */
6832 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6833 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006834 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006835#ifdef USE_OPENSSL
6836 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006837 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006838 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006839 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006840 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006841#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006842 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006843
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006844 /* Check multi-process mode compatibility for the current proxy */
6845 if (global.nbproc > 1) {
6846 int nbproc = 0;
6847 if (curproxy->bind_proc) {
6848 int proc;
6849 for (proc = 0; proc < global.nbproc; proc++) {
6850 if (curproxy->bind_proc & (1 << proc)) {
6851 nbproc++;
6852 }
6853 }
6854 } else {
6855 nbproc = global.nbproc;
6856 }
6857 if (curproxy->table.peers.name) {
6858 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6859 curproxy->id);
6860 cfgerr++;
6861 }
6862 if (nbproc > 1) {
6863 if (curproxy->uri_auth) {
6864 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6865 curproxy->id);
6866 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6867 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6868 curproxy->id);
6869 }
6870 }
6871 if (curproxy->appsession_name) {
6872 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6873 curproxy->id);
6874 }
6875 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6876 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6877 curproxy->id);
6878 }
6879 }
6880 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006881
6882 /* create the task associated with the proxy */
6883 curproxy->task = task_new();
6884 if (curproxy->task) {
6885 curproxy->task->context = curproxy;
6886 curproxy->task->process = manage_proxy;
6887 /* no need to queue, it will be done automatically if some
6888 * listener gets limited.
6889 */
6890 curproxy->task->expire = TICK_ETERNITY;
6891 } else {
6892 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6893 curproxy->id);
6894 cfgerr++;
6895 }
6896
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897 curproxy = curproxy->next;
6898 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006899
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006900 /* Check multi-process mode compatibility */
6901 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006902 if (global.stats_fe && !global.stats_fe->bind_proc) {
6903 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006904 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006905 }
6906
6907 /* automatically compute fullconn if not set. We must not do it in the
6908 * loop above because cross-references are not yet fully resolved.
6909 */
6910 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6911 /* If <fullconn> is not set, let's set it to 10% of the sum of
6912 * the possible incoming frontend's maxconns.
6913 */
6914 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6915 struct proxy *fe;
6916 int total = 0;
6917
6918 /* sum up the number of maxconns of frontends which
6919 * reference this backend at least once or which are
6920 * the same one ('listen').
6921 */
6922 for (fe = proxy; fe; fe = fe->next) {
6923 struct switching_rule *rule;
6924 struct hdr_exp *exp;
6925 int found = 0;
6926
6927 if (!(fe->cap & PR_CAP_FE))
6928 continue;
6929
6930 if (fe == curproxy) /* we're on a "listen" instance */
6931 found = 1;
6932
6933 if (fe->defbe.be == curproxy) /* "default_backend" */
6934 found = 1;
6935
6936 /* check if a "use_backend" rule matches */
6937 if (!found) {
6938 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006939 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006940 found = 1;
6941 break;
6942 }
6943 }
6944 }
6945
6946 /* check if a "reqsetbe" rule matches */
6947 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6948 if (exp->action == ACT_SETBE &&
6949 (struct proxy *)exp->replace == curproxy) {
6950 found = 1;
6951 break;
6952 }
6953 }
6954
6955 /* now we've checked all possible ways to reference a backend
6956 * from a frontend.
6957 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006958 if (!found)
6959 continue;
6960 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006961 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006962 /* we have the sum of the maxconns in <total>. We only
6963 * keep 10% of that sum to set the default fullconn, with
6964 * a hard minimum of 1 (to avoid a divide by zero).
6965 */
6966 curproxy->fullconn = (total + 9) / 10;
6967 if (!curproxy->fullconn)
6968 curproxy->fullconn = 1;
6969 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006970 }
6971
Willy Tarreau056f5682010-06-06 15:51:11 +02006972 /* initialize stick-tables on backend capable proxies. This must not
6973 * be done earlier because the data size may be discovered while parsing
6974 * other proxies.
6975 */
Godbach9703e662013-12-11 21:11:41 +08006976 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006977 if (curproxy->state == PR_STSTOPPED)
6978 continue;
6979
Godbach9703e662013-12-11 21:11:41 +08006980 if (!stktable_init(&curproxy->table)) {
6981 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6982 cfgerr++;
6983 }
6984 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006985
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006986 /*
6987 * Recount currently required checks.
6988 */
6989
6990 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6991 int optnum;
6992
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006993 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6994 if (curproxy->options & cfg_opts[optnum].val)
6995 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006996
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006997 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6998 if (curproxy->options2 & cfg_opts2[optnum].val)
6999 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007000 }
7001
Willy Tarreau122541c2011-09-07 21:24:49 +02007002 if (peers) {
7003 struct peers *curpeers = peers, **last;
7004 struct peer *p, *pb;
7005
7006 /* Remove all peers sections which don't have a valid listener.
7007 * This can happen when a peers section is never referenced and
7008 * does not contain a local peer.
7009 */
7010 last = &peers;
7011 while (*last) {
7012 curpeers = *last;
7013 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007014 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007015 last = &curpeers->next;
7016 continue;
7017 }
7018
7019 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7020 curpeers->id, localpeer);
7021
7022 p = curpeers->remote;
7023 while (p) {
7024 pb = p->next;
7025 free(p->id);
7026 free(p);
7027 p = pb;
7028 }
7029
7030 /* Destroy and unlink this curpeers section.
7031 * Note: curpeers is backed up into *last.
7032 */
7033 free(curpeers->id);
7034 curpeers = curpeers->next;
7035 free(*last);
7036 *last = curpeers;
7037 }
7038 }
7039
Willy Tarreau34eb6712011-10-24 18:15:04 +02007040 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007041 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007042 MEM_F_SHARED);
7043
Willy Tarreaubb925012009-07-23 13:36:36 +02007044 if (cfgerr > 0)
7045 err_code |= ERR_ALERT | ERR_FATAL;
7046 out:
7047 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007048}
7049
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007050/*
7051 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7052 * parsing sessions.
7053 */
7054void cfg_register_keywords(struct cfg_kw_list *kwl)
7055{
7056 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7057}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007058
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007059/*
7060 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7061 */
7062void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7063{
7064 LIST_DEL(&kwl->list);
7065 LIST_INIT(&kwl->list);
7066}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007067
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007068/* this function register new section in the haproxy configuration file.
7069 * <section_name> is the name of this new section and <section_parser>
7070 * is the called parser. If two section declaration have the same name,
7071 * only the first declared is used.
7072 */
7073int cfg_register_section(char *section_name,
7074 int (*section_parser)(const char *, int, char **, int))
7075{
7076 struct cfg_section *cs;
7077
7078 cs = calloc(1, sizeof(*cs));
7079 if (!cs) {
7080 Alert("register section '%s': out of memory.\n", section_name);
7081 return 0;
7082 }
7083
7084 cs->section_name = section_name;
7085 cs->section_parser = section_parser;
7086
7087 LIST_ADDQ(&sections, &cs->list);
7088
7089 return 1;
7090}
7091
Willy Tarreaubaaee002006-06-26 02:48:02 +02007092/*
7093 * Local variables:
7094 * c-indent-level: 8
7095 * c-basic-offset: 8
7096 * End:
7097 */