blob: c4f092fa9fc0f2bd1428e9acbdd1c97b3e52c911 [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
Willy Tarreau7c29f1e2014-04-29 19:55:25 +02001408 if (high >= sizeof(long) * 8) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001409 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
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004065 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4066 Warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'option redispatch', and will not be supported by future versions.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 /* enable reconnections to dispatch */
4070 curproxy->options |= PR_O_REDISP;
4071 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004072 else if (!strcmp(args[0], "http-check")) {
4073 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004075
4076 if (strcmp(args[1], "disable-on-404") == 0) {
4077 /* enable a graceful server shutdown on an HTTP 404 response */
4078 curproxy->options |= PR_O_DISABLE404;
4079 }
Willy Tarreauef781042010-01-27 11:53:01 +01004080 else if (strcmp(args[1], "send-state") == 0) {
4081 /* enable emission of the apparent state of a server in HTTP checks */
4082 curproxy->options2 |= PR_O2_CHK_SNDST;
4083 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004084 else if (strcmp(args[1], "expect") == 0) {
4085 const char *ptr_arg;
4086 int cur_arg;
4087
4088 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4089 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093
4094 cur_arg = 2;
4095 /* consider exclamation marks, sole or at the beginning of a word */
4096 while (*(ptr_arg = args[cur_arg])) {
4097 while (*ptr_arg == '!') {
4098 curproxy->options2 ^= PR_O2_EXP_INV;
4099 ptr_arg++;
4100 }
4101 if (*ptr_arg)
4102 break;
4103 cur_arg++;
4104 }
4105 /* now ptr_arg points to the beginning of a word past any possible
4106 * exclamation mark, and cur_arg is the argument which holds this word.
4107 */
4108 if (strcmp(ptr_arg, "status") == 0) {
4109 if (!*(args[cur_arg + 1])) {
4110 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4111 file, linenum, args[0], args[1], ptr_arg);
4112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
4114 }
4115 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004116 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004117 curproxy->expect_str = strdup(args[cur_arg + 1]);
4118 }
4119 else if (strcmp(ptr_arg, "string") == 0) {
4120 if (!*(args[cur_arg + 1])) {
4121 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4122 file, linenum, args[0], args[1], ptr_arg);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004127 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004128 curproxy->expect_str = strdup(args[cur_arg + 1]);
4129 }
4130 else if (strcmp(ptr_arg, "rstatus") == 0) {
4131 if (!*(args[cur_arg + 1])) {
4132 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4133 file, linenum, args[0], args[1], ptr_arg);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004138 free(curproxy->expect_str);
4139 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4140 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004141 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4142 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4143 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4144 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148 }
4149 else if (strcmp(ptr_arg, "rstring") == 0) {
4150 if (!*(args[cur_arg + 1])) {
4151 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4152 file, linenum, args[0], args[1], ptr_arg);
4153 err_code |= ERR_ALERT | ERR_FATAL;
4154 goto out;
4155 }
4156 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004157 free(curproxy->expect_str);
4158 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4159 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004160 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4161 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4162 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4163 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
4166 }
4167 }
4168 else {
4169 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4170 file, linenum, args[0], args[1], ptr_arg);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004175 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004176 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 +02004177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004179 }
4180 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004181 else if (!strcmp(args[0], "tcp-check")) {
4182 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4183 err_code |= ERR_WARN;
4184
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004185 if (strcmp(args[1], "connect") == 0) {
4186 const char *ptr_arg;
4187 int cur_arg;
4188 struct tcpcheck_rule *tcpcheck;
4189 struct list *l;
4190
4191 /* check if first rule is also a 'connect' action */
4192 l = (struct list *)&curproxy->tcpcheck_rules;
4193 if (l->p != l->n) {
4194 tcpcheck = (struct tcpcheck_rule *)l->n;
4195 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4196 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4197 file, linenum);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201 }
4202
4203 cur_arg = 2;
4204 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4205 tcpcheck->action = TCPCHK_ACT_CONNECT;
4206
4207 /* parsing each parameters to fill up the rule */
4208 while (*(ptr_arg = args[cur_arg])) {
4209 /* tcp port */
4210 if (strcmp(args[cur_arg], "port") == 0) {
4211 if ( (atol(args[cur_arg + 1]) > 65535) ||
4212 (atol(args[cur_arg + 1]) < 1) ){
4213 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4214 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 }
4218 tcpcheck->port = atol(args[cur_arg + 1]);
4219 cur_arg += 2;
4220 }
4221 /* send proxy protocol */
4222 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4223 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4224 cur_arg++;
4225 }
4226#ifdef USE_OPENSSL
4227 else if (strcmp(args[cur_arg], "ssl") == 0) {
4228 curproxy->options |= PR_O_TCPCHK_SSL;
4229 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4230 cur_arg++;
4231 }
4232#endif /* USE_OPENSSL */
4233 else {
4234#ifdef USE_OPENSSL
4235 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4236#else /* USE_OPENSSL */
4237 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4238#endif /* USE_OPENSSL */
4239 file, linenum, args[0], args[1], args[cur_arg]);
4240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
4242 }
4243
4244 }
4245
4246 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4247 }
4248 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004249 if (! *(args[2]) ) {
4250 /* SEND string expected */
4251 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4252 file, linenum, args[0], args[1], args[2]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 } else {
4256 struct tcpcheck_rule *tcpcheck;
4257
4258 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4259
4260 tcpcheck->action = TCPCHK_ACT_SEND;
4261 tcpcheck->string_len = strlen(args[2]);
4262 tcpcheck->string = strdup(args[2]);
4263 tcpcheck->expect_regex = NULL;
4264
4265 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4266 }
4267 }
4268 else if (strcmp(args[1], "send-binary") == 0) {
4269 if (! *(args[2]) ) {
4270 /* SEND binary string expected */
4271 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4272 file, linenum, args[0], args[1], args[2]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 } else {
4276 struct tcpcheck_rule *tcpcheck;
4277 char *err = NULL;
4278
4279 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4280
4281 tcpcheck->action = TCPCHK_ACT_SEND;
4282 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4283 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4284 file, linenum, args[0], args[1], args[2], err);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
4288 tcpcheck->expect_regex = NULL;
4289
4290 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4291 }
4292 }
4293 else if (strcmp(args[1], "expect") == 0) {
4294 const char *ptr_arg;
4295 int cur_arg;
4296 int inverse = 0;
4297
4298 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4299 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303
4304 cur_arg = 2;
4305 /* consider exclamation marks, sole or at the beginning of a word */
4306 while (*(ptr_arg = args[cur_arg])) {
4307 while (*ptr_arg == '!') {
4308 inverse = !inverse;
4309 ptr_arg++;
4310 }
4311 if (*ptr_arg)
4312 break;
4313 cur_arg++;
4314 }
4315 /* now ptr_arg points to the beginning of a word past any possible
4316 * exclamation mark, and cur_arg is the argument which holds this word.
4317 */
4318 if (strcmp(ptr_arg, "binary") == 0) {
4319 if (!*(args[cur_arg + 1])) {
4320 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4321 file, linenum, args[0], args[1], ptr_arg);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325 struct tcpcheck_rule *tcpcheck;
4326 char *err = NULL;
4327
4328 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4329
4330 tcpcheck->action = TCPCHK_ACT_EXPECT;
4331 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4332 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4333 file, linenum, args[0], args[1], args[2], err);
4334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
4336 }
4337 tcpcheck->expect_regex = NULL;
4338 tcpcheck->inverse = inverse;
4339
4340 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4341 }
4342 else if (strcmp(ptr_arg, "string") == 0) {
4343 if (!*(args[cur_arg + 1])) {
4344 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4345 file, linenum, args[0], args[1], ptr_arg);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349 struct tcpcheck_rule *tcpcheck;
4350
4351 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4352
4353 tcpcheck->action = TCPCHK_ACT_EXPECT;
4354 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4355 tcpcheck->string = strdup(args[cur_arg + 1]);
4356 tcpcheck->expect_regex = NULL;
4357 tcpcheck->inverse = inverse;
4358
4359 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4360 }
4361 else if (strcmp(ptr_arg, "rstring") == 0) {
4362 if (!*(args[cur_arg + 1])) {
4363 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4364 file, linenum, args[0], args[1], ptr_arg);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368 struct tcpcheck_rule *tcpcheck;
4369
4370 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4371
4372 tcpcheck->action = TCPCHK_ACT_EXPECT;
4373 tcpcheck->string_len = 0;
4374 tcpcheck->string = NULL;
4375 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4376 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4377 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4378 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
4381 }
4382 tcpcheck->inverse = inverse;
4383
4384 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4385 }
4386 else {
4387 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4388 file, linenum, args[0], args[1], ptr_arg);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
4392 }
4393 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004394 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004399 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004400 if (curproxy == &defproxy) {
4401 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004404 }
4405
Willy Tarreaub80c2302007-11-30 20:51:32 +01004406 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004408
4409 if (strcmp(args[1], "fail") == 0) {
4410 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004411 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004412 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4413 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004416 }
4417
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004418 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4419 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4420 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004423 }
4424 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4425 }
4426 else {
4427 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004430 }
4431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432#ifdef TPROXY
4433 else if (!strcmp(args[0], "transparent")) {
4434 /* enable transparent proxy connections */
4435 curproxy->options |= PR_O_TRANSP;
4436 }
4437#endif
4438 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004439 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004441
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 if (*(args[1]) == 0) {
4443 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 }
4447 curproxy->maxconn = atol(args[1]);
4448 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004449 else if (!strcmp(args[0], "backlog")) { /* backlog */
4450 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004452
4453 if (*(args[1]) == 0) {
4454 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004457 }
4458 curproxy->backlog = atol(args[1]);
4459 }
Willy Tarreau86034312006-12-29 00:10:33 +01004460 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004461 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004463
Willy Tarreau86034312006-12-29 00:10:33 +01004464 if (*(args[1]) == 0) {
4465 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004468 }
4469 curproxy->fullconn = atol(args[1]);
4470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4472 if (*(args[1]) == 0) {
4473 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004477 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4478 if (err) {
4479 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4480 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004483 }
4484 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
4486 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004487 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004488 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004489 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004490
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 if (curproxy == &defproxy) {
4492 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004496 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004497 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004498
Willy Tarreau902636f2013-03-10 19:44:48 +01004499 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004500 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004501 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004502 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004503 goto out;
4504 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004505
4506 proto = protocol_by_family(sk->ss_family);
4507 if (!proto || !proto->connect) {
4508 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4509 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
4512 }
4513
4514 if (port1 != port2) {
4515 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4516 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004520
4521 if (!port1) {
4522 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4523 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
4526 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004527
Willy Tarreaud5191e72010-02-09 20:50:45 +01004528 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004529 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
4531 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004532 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004533 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004534
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004535 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4536 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004541 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004542 /**
4543 * The syntax for hash-type config element is
4544 * hash-type {map-based|consistent} [[<algo>] avalanche]
4545 *
4546 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4547 */
4548 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004549
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4551 err_code |= ERR_WARN;
4552
4553 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004554 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4555 }
4556 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004557 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4558 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004559 else if (strcmp(args[1], "avalanche") == 0) {
4560 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]);
4561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004563 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004564 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004565 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
Bhaskar98634f02013-10-29 23:30:51 -04004569
4570 /* set the hash function to use */
4571 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004572 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004573 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004574
4575 /* if consistent with no argument, then avalanche modifier is also applied */
4576 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4577 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004578 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004579 /* set the hash function */
4580 if (!strcmp(args[2], "sdbm")) {
4581 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4582 }
4583 else if (!strcmp(args[2], "djb2")) {
4584 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004585 } else if (!strcmp(args[2], "wt6")) {
4586 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004587 }
4588 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004589 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 -05004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
4592 }
4593
4594 /* set the hash modifier */
4595 if (!strcmp(args[3], "avalanche")) {
4596 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4597 }
4598 else if (*args[3]) {
4599 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004603 }
William Lallemanda73203e2012-03-12 12:48:57 +01004604 }
William Lallemanda73203e2012-03-12 12:48:57 +01004605 else if (strcmp(args[0], "unique-id-format") == 0) {
4606 if (!*(args[1])) {
4607 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
William Lallemand3203ff42012-11-11 17:30:56 +01004611 if (*(args[2])) {
4612 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
4615 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004616 free(curproxy->conf.uniqueid_format_string);
4617 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004618
Willy Tarreau62a61232013-04-12 18:13:46 +02004619 free(curproxy->conf.uif_file);
4620 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4621 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004622 }
William Lallemanda73203e2012-03-12 12:48:57 +01004623
4624 else if (strcmp(args[0], "unique-id-header") == 0) {
4625 if (!*(args[1])) {
4626 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4627 err_code |= ERR_ALERT | ERR_FATAL;
4628 goto out;
4629 }
4630 free(curproxy->header_unique_id);
4631 curproxy->header_unique_id = strdup(args[1]);
4632 }
4633
William Lallemand723b73a2012-02-08 16:37:49 +01004634 else if (strcmp(args[0], "log-format") == 0) {
4635 if (!*(args[1])) {
4636 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
William Lallemand3203ff42012-11-11 17:30:56 +01004640 if (*(args[2])) {
4641 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
4644 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004645
Willy Tarreau62a61232013-04-12 18:13:46 +02004646 if (curproxy->conf.logformat_string != default_http_log_format &&
4647 curproxy->conf.logformat_string != default_tcp_log_format &&
4648 curproxy->conf.logformat_string != clf_http_log_format)
4649 free(curproxy->conf.logformat_string);
4650 curproxy->conf.logformat_string = strdup(args[1]);
4651
4652 free(curproxy->conf.lfs_file);
4653 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4654 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004655
4656 /* get a chance to improve log-format error reporting by
4657 * reporting the correct line-number when possible.
4658 */
4659 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4660 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4661 file, linenum, curproxy->id);
4662 err_code |= ERR_WARN;
4663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 }
William Lallemand723b73a2012-02-08 16:37:49 +01004665
William Lallemand0f99e342011-10-12 17:50:54 +02004666 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4667 /* delete previous herited or defined syslog servers */
4668 struct logsrv *back;
4669
4670 if (*(args[1]) != 0) {
4671 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675
William Lallemand723b73a2012-02-08 16:37:49 +01004676 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4677 LIST_DEL(&tmplogsrv->list);
4678 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004679 }
4680 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004682 struct logsrv *logsrv;
4683
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004685 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004686 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004687 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004688 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004689 LIST_INIT(&node->list);
4690 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 }
4693 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004694 struct sockaddr_storage *sk;
4695 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004696
4697 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698
William Lallemand0f99e342011-10-12 17:50:54 +02004699 logsrv->facility = get_log_facility(args[2]);
4700 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004702 err_code |= ERR_ALERT | ERR_FATAL;
4703 goto out;
4704
Willy Tarreaubaaee002006-06-26 02:48:02 +02004705 }
4706
William Lallemand0f99e342011-10-12 17:50:54 +02004707 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004709 logsrv->level = get_log_level(args[3]);
4710 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 }
4716 }
4717
William Lallemand0f99e342011-10-12 17:50:54 +02004718 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004719 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004720 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004721 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004722 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004726 }
4727 }
4728
Willy Tarreau902636f2013-03-10 19:44:48 +01004729 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004730 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004731 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004732 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004733 goto out;
4734 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004735
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004736 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004737
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004738 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004739 if (port1 != port2) {
4740 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4741 file, linenum, args[0], args[1]);
4742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
4744 }
4745
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004746 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004747 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
William Lallemand0f99e342011-10-12 17:50:54 +02004749
4750 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
4752 else {
4753 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4754 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 }
4759 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004761 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004762 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004763 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004764
Willy Tarreau977b8e42006-12-29 14:19:17 +01004765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004767
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004769 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4770 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004774
4775 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004776 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4777 free(curproxy->conn_src.iface_name);
4778 curproxy->conn_src.iface_name = NULL;
4779 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004780
Willy Tarreau902636f2013-03-10 19:44:48 +01004781 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004782 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004783 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004784 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004785 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004786 goto out;
4787 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004788
4789 proto = protocol_by_family(sk->ss_family);
4790 if (!proto || !proto->connect) {
4791 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004792 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004793 err_code |= ERR_ALERT | ERR_FATAL;
4794 goto out;
4795 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004796
4797 if (port1 != port2) {
4798 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4799 file, linenum, args[0], args[1]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
4803
Willy Tarreauef9a3602012-12-08 22:29:20 +01004804 curproxy->conn_src.source_addr = *sk;
4805 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004806
4807 cur_arg = 2;
4808 while (*(args[cur_arg])) {
4809 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004810#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4811#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004812 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004813 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4814 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004817 }
4818#endif
4819 if (!*args[cur_arg + 1]) {
4820 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4821 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004824 }
4825
4826 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004827 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4828 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004829 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004830 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4831 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004832 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4833 char *name, *end;
4834
4835 name = args[cur_arg+1] + 7;
4836 while (isspace(*name))
4837 name++;
4838
4839 end = name;
4840 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4841 end++;
4842
Willy Tarreauef9a3602012-12-08 22:29:20 +01004843 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4844 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4845 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4846 curproxy->conn_src.bind_hdr_len = end - name;
4847 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4848 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4849 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004850
4851 /* now look for an occurrence number */
4852 while (isspace(*end))
4853 end++;
4854 if (*end == ',') {
4855 end++;
4856 name = end;
4857 if (*end == '-')
4858 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004859 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004860 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004861 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004862 }
4863
Willy Tarreauef9a3602012-12-08 22:29:20 +01004864 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004865 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4866 " occurrences values smaller than %d.\n",
4867 file, linenum, MAX_HDR_HISTORY);
4868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004871 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01004872 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004873
Willy Tarreau902636f2013-03-10 19:44:48 +01004874 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004875 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004876 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004877 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004879 goto out;
4880 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004881
4882 proto = protocol_by_family(sk->ss_family);
4883 if (!proto || !proto->connect) {
4884 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4885 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
4888 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004889
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004890 if (port1 != port2) {
4891 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4892 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004896 curproxy->conn_src.tproxy_addr = *sk;
4897 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004898 }
4899 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004900#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004901 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004902#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004903#else /* no TPROXY support */
4904 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004905 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004906 err_code |= ERR_ALERT | ERR_FATAL;
4907 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004908#endif
4909 cur_arg += 2;
4910 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004911 }
4912
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004913 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4914#ifdef SO_BINDTODEVICE
4915 if (!*args[cur_arg + 1]) {
4916 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4917 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004920 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004921 free(curproxy->conn_src.iface_name);
4922 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4923 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 global.last_checks |= LSTCHK_NETADM;
4925#else
4926 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4927 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004930#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004931 cur_arg += 2;
4932 continue;
4933 }
4934 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004935 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004940 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4941 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4942 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953
4954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004988 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004994 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004995 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005001
5002 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5003 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 +01005004 }
5005 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005007 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005008 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005011
5012 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5013 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 +01005014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022
5023 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005024 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005025 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005030 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005031 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005032 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 }
5036 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005037 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005038 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005039 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
5043 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005045 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005046 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
5050 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005052 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005053 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005057 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005059 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005060 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005062 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005065 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005066
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 if (curproxy == &defproxy) {
5068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005072 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 if (*(args[1]) == 0) {
5076 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005080
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005081 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005082 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5083 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5084 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005088 err_code |= warnif_cond_conflicts(cond,
5089 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5090 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005091 }
5092 else if (*args[2]) {
5093 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5094 file, linenum, args[0], args[2]);
5095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
5097 }
5098
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005099 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005100 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005101 wl->s = strdup(args[1]);
5102 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005103 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
5105 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5108 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005112
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005114 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005115 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
5119 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005121 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005128 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005129 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
5133 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5136 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
5140
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005142 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005143 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
5147 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005150 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
5154 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005156 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005157 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
5161 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005162 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005163
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 if (curproxy == &defproxy) {
5165 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005169 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 if (*(args[1]) == 0) {
5173 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005178 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005179 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5180 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5181 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005185 err_code |= warnif_cond_conflicts(cond,
5186 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5187 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005188 }
5189 else if (*args[2]) {
5190 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5191 file, linenum, args[0], args[2]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
5195
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005196 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005197 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005198 wl->s = strdup(args[1]);
5199 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 }
5201 else if (!strcmp(args[0], "errorloc") ||
5202 !strcmp(args[0], "errorloc302") ||
5203 !strcmp(args[0], "errorloc303")) { /* error location */
5204 int errnum, errlen;
5205 char *err;
5206
Willy Tarreau977b8e42006-12-29 14:19:17 +01005207 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005209
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005211 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
5215
5216 errnum = atol(args[1]);
5217 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005218 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5219 err = malloc(errlen);
5220 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005222 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5223 err = malloc(errlen);
5224 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
5226
Willy Tarreau0f772532006-12-23 20:51:41 +01005227 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5228 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005229 chunk_destroy(&curproxy->errmsg[rc]);
5230 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005231 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005234
5235 if (rc >= HTTP_ERR_SIZE) {
5236 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5237 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 free(err);
5239 }
5240 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005241 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5242 int errnum, errlen, fd;
5243 char *err;
5244 struct stat stat;
5245
5246 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005247 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005248
5249 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005250 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005253 }
5254
5255 fd = open(args[2], O_RDONLY);
5256 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5257 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5258 file, linenum, args[2], args[1]);
5259 if (fd >= 0)
5260 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005263 }
5264
Willy Tarreau27a674e2009-08-17 07:23:33 +02005265 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005266 errlen = stat.st_size;
5267 } else {
5268 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005269 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005271 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005272 }
5273
5274 err = malloc(errlen); /* malloc() must succeed during parsing */
5275 errnum = read(fd, err, errlen);
5276 if (errnum != errlen) {
5277 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5278 file, linenum, args[2], args[1]);
5279 close(fd);
5280 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005283 }
5284 close(fd);
5285
5286 errnum = atol(args[1]);
5287 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5288 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005289 chunk_destroy(&curproxy->errmsg[rc]);
5290 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005291 break;
5292 }
5293 }
5294
5295 if (rc >= HTTP_ERR_SIZE) {
5296 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5297 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005299 free(err);
5300 }
5301 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005302 else if (!strcmp(args[0], "compression")) {
5303 struct comp *comp;
5304 if (curproxy->comp == NULL) {
5305 comp = calloc(1, sizeof(struct comp));
5306 curproxy->comp = comp;
5307 } else {
5308 comp = curproxy->comp;
5309 }
5310
5311 if (!strcmp(args[1], "algo")) {
5312 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005313 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005314
William Lallemand82fe75c2012-10-23 10:25:10 +02005315 cur_arg = 2;
5316 if (!*args[cur_arg]) {
5317 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5318 file, linenum, args[0]);
5319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 while (*(args[cur_arg])) {
5323 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5324 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5325 file, linenum, args[0], args[cur_arg]);
5326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
William Lallemand552df672012-11-07 13:21:47 +01005329 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5330 curproxy->comp->algos->end(&ctx);
5331 } else {
5332 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5333 file, linenum, args[0], args[cur_arg]);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005337 cur_arg ++;
5338 continue;
5339 }
5340 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005341 else if (!strcmp(args[1], "offload")) {
5342 comp->offload = 1;
5343 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005344 else if (!strcmp(args[1], "type")) {
5345 int cur_arg;
5346 cur_arg = 2;
5347 if (!*args[cur_arg]) {
5348 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5349 file, linenum, args[0]);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
5353 while (*(args[cur_arg])) {
5354 comp_append_type(comp, args[cur_arg]);
5355 cur_arg ++;
5356 continue;
5357 }
5358 }
5359 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005360 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005361 file, linenum, args[0]);
5362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
5364 }
5365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005367 struct cfg_kw_list *kwl;
5368 int index;
5369
5370 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5371 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5372 if (kwl->kw[index].section != CFG_LISTEN)
5373 continue;
5374 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5375 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005376 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005377 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005378 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005381 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005382 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005383 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005384 err_code |= ERR_WARN;
5385 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005386 }
Willy Tarreau93893792009-07-23 13:19:11 +02005387 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005388 }
5389 }
5390 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005391
Willy Tarreau6daf3432008-01-22 16:44:08 +01005392 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 }
Willy Tarreau93893792009-07-23 13:19:11 +02005396 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005397 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005398 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399}
5400
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005401int
5402cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5403{
5404
5405 int err_code = 0;
5406 const char *err;
5407
5408 if (!strcmp(args[0], "userlist")) { /* new userlist */
5409 struct userlist *newul;
5410
5411 if (!*args[1]) {
5412 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5413 file, linenum, args[0]);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 }
5417
5418 err = invalid_char(args[1]);
5419 if (err) {
5420 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5421 file, linenum, *err, args[0], args[1]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425
5426 for (newul = userlist; newul; newul = newul->next)
5427 if (!strcmp(newul->name, args[1])) {
5428 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5429 file, linenum, args[1]);
5430 err_code |= ERR_WARN;
5431 goto out;
5432 }
5433
5434 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5435 if (!newul) {
5436 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5437 err_code |= ERR_ALERT | ERR_ABORT;
5438 goto out;
5439 }
5440
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005441 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005442 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005443 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5444 err_code |= ERR_ALERT | ERR_ABORT;
5445 goto out;
5446 }
5447
5448 newul->next = userlist;
5449 userlist = newul;
5450
5451 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005452 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005453 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005454 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005455
5456 if (!*args[1]) {
5457 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5458 file, linenum, args[0]);
5459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
5461 }
5462
5463 err = invalid_char(args[1]);
5464 if (err) {
5465 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5466 file, linenum, *err, args[0], args[1]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005471 for (ag = userlist->groups; ag; ag = ag->next)
5472 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005473 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5474 file, linenum, args[1], userlist->name);
5475 err_code |= ERR_ALERT;
5476 goto out;
5477 }
5478
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005479 ag = calloc(1, sizeof(*ag));
5480 if (!ag) {
5481 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5482 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005483 goto out;
5484 }
5485
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005486 ag->name = strdup(args[1]);
5487 if (!ag) {
5488 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5489 err_code |= ERR_ALERT | ERR_ABORT;
5490 goto out;
5491 }
5492
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005493 cur_arg = 2;
5494
5495 while (*args[cur_arg]) {
5496 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005497 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005498 cur_arg += 2;
5499 continue;
5500 } else {
5501 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5502 file, linenum, args[0]);
5503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
5506 }
5507
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005508 ag->next = userlist->groups;
5509 userlist->groups = ag;
5510
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005511 } else if (!strcmp(args[0], "user")) { /* new user */
5512 struct auth_users *newuser;
5513 int cur_arg;
5514
5515 if (!*args[1]) {
5516 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5517 file, linenum, args[0]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521
5522 for (newuser = userlist->users; newuser; newuser = newuser->next)
5523 if (!strcmp(newuser->user, args[1])) {
5524 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5525 file, linenum, args[1], userlist->name);
5526 err_code |= ERR_ALERT;
5527 goto out;
5528 }
5529
5530 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5531 if (!newuser) {
5532 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5533 err_code |= ERR_ALERT | ERR_ABORT;
5534 goto out;
5535 }
5536
5537 newuser->user = strdup(args[1]);
5538
5539 newuser->next = userlist->users;
5540 userlist->users = newuser;
5541
5542 cur_arg = 2;
5543
5544 while (*args[cur_arg]) {
5545 if (!strcmp(args[cur_arg], "password")) {
5546#ifndef CONFIG_HAP_CRYPT
5547 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5548 file, linenum);
5549 err_code |= ERR_ALERT;
5550#endif
5551 newuser->pass = strdup(args[cur_arg + 1]);
5552 cur_arg += 2;
5553 continue;
5554 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5555 newuser->pass = strdup(args[cur_arg + 1]);
5556 newuser->flags |= AU_O_INSECURE;
5557 cur_arg += 2;
5558 continue;
5559 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005560 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005561 cur_arg += 2;
5562 continue;
5563 } else {
5564 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5565 file, linenum, args[0]);
5566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
5568 }
5569 }
5570 } else {
5571 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 }
5574
5575out:
5576 return err_code;
5577}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578
5579/*
5580 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005581 * Returns the error code, 0 if OK, or any combination of :
5582 * - ERR_ABORT: must abort ASAP
5583 * - ERR_FATAL: we can continue parsing but not start the service
5584 * - ERR_WARN: a warning has been emitted
5585 * - ERR_ALERT: an alert has been emitted
5586 * Only the two first ones can stop processing, the two others are just
5587 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005589int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005591 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 FILE *f;
5593 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005594 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005595 struct cfg_section *cs = NULL;
5596 struct cfg_section *ics;
5597
5598 /* Register internal sections */
5599 if (!cfg_register_section("listen", cfg_parse_listen) ||
5600 !cfg_register_section("frontend", cfg_parse_listen) ||
5601 !cfg_register_section("backend", cfg_parse_listen) ||
5602 !cfg_register_section("ruleset", cfg_parse_listen) ||
5603 !cfg_register_section("defaults", cfg_parse_listen) ||
5604 !cfg_register_section("global", cfg_parse_global) ||
5605 !cfg_register_section("userlist", cfg_parse_users) ||
5606 !cfg_register_section("peers", cfg_parse_peers))
5607 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 if ((f=fopen(file,"r")) == NULL)
5610 return -1;
5611
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005612 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005613 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005614 char *end;
5615 char *args[MAX_LINE_ARGS + 1];
5616 char *line = thisline;
5617
Willy Tarreaubaaee002006-06-26 02:48:02 +02005618 linenum++;
5619
5620 end = line + strlen(line);
5621
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005622 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5623 /* Check if we reached the limit and the last char is not \n.
5624 * Watch out for the last line without the terminating '\n'!
5625 */
5626 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005627 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005628 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005629 }
5630
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005632 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 line++;
5634
5635 arg = 0;
5636 args[arg] = line;
5637
5638 while (*line && arg < MAX_LINE_ARGS) {
5639 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5640 * C equivalent value. Other combinations left unchanged (eg: \1).
5641 */
5642 if (*line == '\\') {
5643 int skip = 0;
5644 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5645 *line = line[1];
5646 skip = 1;
5647 }
5648 else if (line[1] == 'r') {
5649 *line = '\r';
5650 skip = 1;
5651 }
5652 else if (line[1] == 'n') {
5653 *line = '\n';
5654 skip = 1;
5655 }
5656 else if (line[1] == 't') {
5657 *line = '\t';
5658 skip = 1;
5659 }
5660 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005661 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 unsigned char hex1, hex2;
5663 hex1 = toupper(line[2]) - '0';
5664 hex2 = toupper(line[3]) - '0';
5665 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5666 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5667 *line = (hex1<<4) + hex2;
5668 skip = 3;
5669 }
5670 else {
5671 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
5674 }
5675 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005676 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 end -= skip;
5678 }
5679 line++;
5680 }
5681 else if (*line == '#' || *line == '\n' || *line == '\r') {
5682 /* end of string, end of loop */
5683 *line = 0;
5684 break;
5685 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005686 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005688 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005689 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690 line++;
5691 args[++arg] = line;
5692 }
5693 else {
5694 line++;
5695 }
5696 }
5697
5698 /* empty line */
5699 if (!**args)
5700 continue;
5701
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005702 if (*line) {
5703 /* we had to stop due to too many args.
5704 * Let's terminate the string, print the offending part then cut the
5705 * last arg.
5706 */
5707 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5708 line++;
5709 *line = '\0';
5710
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005711 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005712 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005713 err_code |= ERR_ALERT | ERR_FATAL;
5714 args[arg] = line;
5715 }
5716
Willy Tarreau540abe42007-05-02 20:50:16 +02005717 /* zero out remaining args and ensure that at least one entry
5718 * is zeroed out.
5719 */
5720 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 args[arg] = line;
5722 }
5723
Willy Tarreau3842f002009-06-14 11:39:52 +02005724 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005725 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005726 char *tmp;
5727
Willy Tarreau3842f002009-06-14 11:39:52 +02005728 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005729 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005730 for (arg=0; *args[arg+1]; arg++)
5731 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005732 *tmp = '\0'; // fix the next arg to \0
5733 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005734 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005735 else if (!strcmp(args[0], "default")) {
5736 kwm = KWM_DEF;
5737 for (arg=0; *args[arg+1]; arg++)
5738 args[arg] = args[arg+1]; // shift args after inversion
5739 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005740
William Lallemand0f99e342011-10-12 17:50:54 +02005741 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5742 strcmp(args[0], "log") != 0) {
5743 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005744 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005745 }
5746
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005747 /* detect section start */
5748 list_for_each_entry(ics, &sections, list) {
5749 if (strcmp(args[0], ics->section_name) == 0) {
5750 cursection = ics->section_name;
5751 cs = ics;
5752 break;
5753 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005754 }
5755
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005757 if (cs)
5758 err_code |= cs->section_parser(file, linenum, args, kwm);
5759 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005760 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005763
5764 if (err_code & ERR_ABORT)
5765 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005767 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005769 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005770}
5771
Willy Tarreaubb925012009-07-23 13:36:36 +02005772/*
5773 * Returns the error code, 0 if OK, or any combination of :
5774 * - ERR_ABORT: must abort ASAP
5775 * - ERR_FATAL: we can continue parsing but not start the service
5776 * - ERR_WARN: a warning has been emitted
5777 * - ERR_ALERT: an alert has been emitted
5778 * Only the two first ones can stop processing, the two others are just
5779 * indicators.
5780 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005781int check_config_validity()
5782{
5783 int cfgerr = 0;
5784 struct proxy *curproxy = NULL;
5785 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005786 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005787 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005788 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005790 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 /*
5792 * Now, check for the integrity of all that we have collected.
5793 */
5794
5795 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005796 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797
Willy Tarreau193b8c62012-11-22 00:17:38 +01005798 if (!global.tune.max_http_hdr)
5799 global.tune.max_http_hdr = MAX_HTTP_HDR;
5800
5801 if (!global.tune.cookie_len)
5802 global.tune.cookie_len = CAPTURE_LEN;
5803
5804 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5805
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005806 /* Post initialisation of the users and groups lists. */
5807 err_code = userlist_postinit();
5808 if (err_code != ERR_NONE)
5809 goto out;
5810
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005811 /* first, we will invert the proxy list order */
5812 curproxy = NULL;
5813 while (proxy) {
5814 struct proxy *next;
5815
5816 next = proxy->next;
5817 proxy->next = curproxy;
5818 curproxy = proxy;
5819 if (!next)
5820 break;
5821 proxy = next;
5822 }
5823
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005825 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005826 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005827 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005828 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005829 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005830 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005831 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005832
Willy Tarreau050536d2012-10-04 08:47:34 +02005833 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005834 /* proxy ID not set, use automatic numbering with first
5835 * spare entry starting with next_pxid.
5836 */
5837 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5838 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5839 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005840 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005841 next_pxid++;
5842
Willy Tarreau55ea7572007-06-17 19:56:27 +02005843
Willy Tarreaubaaee002006-06-26 02:48:02 +02005844 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005845 /* ensure we don't keep listeners uselessly bound */
5846 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 curproxy = curproxy->next;
5848 continue;
5849 }
5850
Willy Tarreau16a21472012-11-19 12:39:59 +01005851 /* number of processes this proxy is bound to */
5852 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5853
Willy Tarreauff01a212009-03-15 13:46:16 +01005854 switch (curproxy->mode) {
5855 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005856 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005857 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005858 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5859 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005860 cfgerr++;
5861 }
5862
5863 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005864 Warning("config : servers will be ignored for %s '%s'.\n",
5865 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005866 break;
5867
5868 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005869 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005870 break;
5871
5872 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01005873 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01005874 break;
5875 }
5876
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005877 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005878 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005879 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005880 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5881 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005882 cfgerr++;
5883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005885 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005886 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5887 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005888 cfgerr++;
5889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005891 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005892 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5893 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005894 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005895 }
5896 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005897 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005898 /* If no LB algo is set in a backend, and we're not in
5899 * transparent mode, dispatch mode nor proxy mode, we
5900 * want to use balance roundrobin by default.
5901 */
5902 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5903 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904 }
5905 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005906
Willy Tarreau1620ec32011-08-06 17:05:02 +02005907 if (curproxy->options & PR_O_DISPATCH)
5908 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5909 else if (curproxy->options & PR_O_HTTP_PROXY)
5910 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5911 else if (curproxy->options & PR_O_TRANSP)
5912 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005913
Willy Tarreau1620ec32011-08-06 17:05:02 +02005914 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5915 if (curproxy->options & PR_O_DISABLE404) {
5916 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5917 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5918 err_code |= ERR_WARN;
5919 curproxy->options &= ~PR_O_DISABLE404;
5920 }
5921 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5922 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5923 "send-state", proxy_type_str(curproxy), curproxy->id);
5924 err_code |= ERR_WARN;
5925 curproxy->options &= ~PR_O2_CHK_SNDST;
5926 }
Willy Tarreauef781042010-01-27 11:53:01 +01005927 }
5928
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005929 /* if a default backend was specified, let's find it */
5930 if (curproxy->defbe.name) {
5931 struct proxy *target;
5932
Alex Williams96532db2009-11-01 21:27:13 -05005933 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005934 if (!target) {
5935 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5936 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005937 cfgerr++;
5938 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005939 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5940 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005941 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005942 } else {
5943 free(curproxy->defbe.name);
5944 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005945 /* we force the backend to be present on at least all of
5946 * the frontend's processes.
5947 */
5948 target->bind_proc = curproxy->bind_proc ?
5949 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005950
5951 /* Emit a warning if this proxy also has some servers */
5952 if (curproxy->srv) {
5953 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5954 curproxy->id);
5955 err_code |= ERR_WARN;
5956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 }
5958 }
5959
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005960 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005961 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5962 /* map jump target for ACT_SETBE in req_rep chain */
5963 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005964 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005965 struct proxy *target;
5966
Willy Tarreaua496b602006-12-17 23:15:24 +01005967 if (exp->action != ACT_SETBE)
5968 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005969
Alex Williams96532db2009-11-01 21:27:13 -05005970 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005971 if (!target) {
5972 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5973 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005974 cfgerr++;
5975 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005976 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5977 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005978 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005979 } else {
5980 free((void *)exp->replace);
5981 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005982 /* we force the backend to be present on at least all of
5983 * the frontend's processes.
5984 */
5985 target->bind_proc = curproxy->bind_proc ?
5986 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005987 }
5988 }
5989 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005990
5991 /* find the target proxy for 'use_backend' rules */
5992 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005993 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01005994 struct logformat_node *node;
5995 char *pxname;
5996
5997 /* Try to parse the string as a log format expression. If the result
5998 * of the parsing is only one entry containing a simple string, then
5999 * it's a standard string corresponding to a static rule, thus the
6000 * parsing is cancelled and be.name is restored to be resolved.
6001 */
6002 pxname = rule->be.name;
6003 LIST_INIT(&rule->be.expr);
6004 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6005 curproxy->conf.args.file, curproxy->conf.args.line);
6006 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6007
6008 if (!LIST_ISEMPTY(&rule->be.expr)) {
6009 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6010 rule->dynamic = 1;
6011 free(pxname);
6012 continue;
6013 }
6014 /* simple string: free the expression and fall back to static rule */
6015 free(node->arg);
6016 free(node);
6017 }
6018
6019 rule->dynamic = 0;
6020 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006021
Alex Williams96532db2009-11-01 21:27:13 -05006022 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006023
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006024 if (!target) {
6025 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6026 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006027 cfgerr++;
6028 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006029 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6030 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006031 cfgerr++;
6032 } else {
6033 free((void *)rule->be.name);
6034 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006035 /* we force the backend to be present on at least all of
6036 * the frontend's processes.
6037 */
6038 target->bind_proc = curproxy->bind_proc ?
6039 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006040 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006041 }
6042
6043 /* find the target proxy for 'use_backend' rules */
6044 list_for_each_entry(srule, &curproxy->server_rules, list) {
6045 struct server *target = findserver(curproxy, srule->srv.name);
6046
6047 if (!target) {
6048 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6049 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6050 cfgerr++;
6051 continue;
6052 }
6053 free((void *)srule->srv.name);
6054 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006055 }
6056
Emeric Brunb982a3d2010-01-04 15:45:53 +01006057 /* find the target table for 'stick' rules */
6058 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6059 struct proxy *target;
6060
Emeric Brun1d33b292010-01-04 15:47:17 +01006061 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6062 if (mrule->flags & STK_IS_STORE)
6063 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6064
Emeric Brunb982a3d2010-01-04 15:45:53 +01006065 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006066 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006067 else
6068 target = curproxy;
6069
6070 if (!target) {
6071 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6072 curproxy->id, mrule->table.name);
6073 cfgerr++;
6074 }
6075 else if (target->table.size == 0) {
6076 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6077 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6078 cfgerr++;
6079 }
Willy Tarreau12785782012-04-27 21:37:17 +02006080 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6081 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006082 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6083 cfgerr++;
6084 }
6085 else {
6086 free((void *)mrule->table.name);
6087 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006088 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006089 }
6090 }
6091
6092 /* find the target table for 'store response' rules */
6093 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6094 struct proxy *target;
6095
Emeric Brun1d33b292010-01-04 15:47:17 +01006096 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6097
Emeric Brunb982a3d2010-01-04 15:45:53 +01006098 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006099 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006100 else
6101 target = curproxy;
6102
6103 if (!target) {
6104 Alert("Proxy '%s': unable to find store table '%s'.\n",
6105 curproxy->id, mrule->table.name);
6106 cfgerr++;
6107 }
6108 else if (target->table.size == 0) {
6109 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6110 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6111 cfgerr++;
6112 }
Willy Tarreau12785782012-04-27 21:37:17 +02006113 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6114 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006115 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6116 cfgerr++;
6117 }
6118 else {
6119 free((void *)mrule->table.name);
6120 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006121 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006122 }
6123 }
6124
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006125 /* find the target table for 'tcp-request' layer 4 rules */
6126 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6127 struct proxy *target;
6128
Willy Tarreaub4c84932013-07-23 19:15:30 +02006129 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006130 continue;
6131
6132 if (trule->act_prm.trk_ctr.table.n)
6133 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6134 else
6135 target = curproxy;
6136
6137 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006138 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6139 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006140 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006141 cfgerr++;
6142 }
6143 else if (target->table.size == 0) {
6144 Alert("Proxy '%s': table '%s' used but not configured.\n",
6145 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6146 cfgerr++;
6147 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006148 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6149 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6150 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 +01006151 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006152 cfgerr++;
6153 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006154 else {
6155 free(trule->act_prm.trk_ctr.table.n);
6156 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006157 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006158 * to pass a list of counters to track and allocate them right here using
6159 * stktable_alloc_data_type().
6160 */
6161 }
6162 }
6163
Willy Tarreaud1f96522010-08-03 19:34:32 +02006164 /* find the target table for 'tcp-request' layer 6 rules */
6165 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6166 struct proxy *target;
6167
Willy Tarreaub4c84932013-07-23 19:15:30 +02006168 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006169 continue;
6170
6171 if (trule->act_prm.trk_ctr.table.n)
6172 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6173 else
6174 target = curproxy;
6175
6176 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006177 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6178 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006179 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006180 cfgerr++;
6181 }
6182 else if (target->table.size == 0) {
6183 Alert("Proxy '%s': table '%s' used but not configured.\n",
6184 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6185 cfgerr++;
6186 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006187 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6188 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6189 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 +01006190 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006191 cfgerr++;
6192 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006193 else {
6194 free(trule->act_prm.trk_ctr.table.n);
6195 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006196 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006197 * to pass a list of counters to track and allocate them right here using
6198 * stktable_alloc_data_type().
6199 */
6200 }
6201 }
6202
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006203 /* move any "block" rules at the beginning of the http-request rules */
6204 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6205 /* insert block_rules into http_req_rules at the beginning */
6206 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6207 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6208 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6209 curproxy->http_req_rules.n = curproxy->block_rules.n;
6210 LIST_INIT(&curproxy->block_rules);
6211 }
6212
Emeric Brun32da3c42010-09-23 18:39:19 +02006213 if (curproxy->table.peers.name) {
6214 struct peers *curpeers = peers;
6215
6216 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6217 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6218 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006219 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006220 break;
6221 }
6222 }
6223
6224 if (!curpeers) {
6225 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6226 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006227 free((void *)curproxy->table.peers.name);
6228 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006229 cfgerr++;
6230 }
6231 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006232 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6233 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006234 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006235 cfgerr++;
6236 }
6237 }
6238
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006239 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006240 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006241 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6242 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6243 "proxy", curproxy->id);
6244 cfgerr++;
6245 goto out_uri_auth_compat;
6246 }
6247
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006248 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006249 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006250 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006251 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006252
Willy Tarreau95fa4692010-02-01 13:05:50 +01006253 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6254 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006255
6256 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006257 uri_auth_compat_req[i++] = "realm";
6258 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6259 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006260
Willy Tarreau95fa4692010-02-01 13:05:50 +01006261 uri_auth_compat_req[i++] = "unless";
6262 uri_auth_compat_req[i++] = "{";
6263 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6264 uri_auth_compat_req[i++] = "}";
6265 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006266
Willy Tarreauff011f22011-01-06 17:51:27 +01006267 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6268 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006269 cfgerr++;
6270 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006271 }
6272
Willy Tarreauff011f22011-01-06 17:51:27 +01006273 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006274
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006275 if (curproxy->uri_auth->auth_realm) {
6276 free(curproxy->uri_auth->auth_realm);
6277 curproxy->uri_auth->auth_realm = NULL;
6278 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006279
6280 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006281 }
6282out_uri_auth_compat:
6283
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006284 /* compile the log format */
6285 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006286 if (curproxy->conf.logformat_string != default_http_log_format &&
6287 curproxy->conf.logformat_string != default_tcp_log_format &&
6288 curproxy->conf.logformat_string != clf_http_log_format)
6289 free(curproxy->conf.logformat_string);
6290 curproxy->conf.logformat_string = NULL;
6291 free(curproxy->conf.lfs_file);
6292 curproxy->conf.lfs_file = NULL;
6293 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006294 }
6295
Willy Tarreau62a61232013-04-12 18:13:46 +02006296 if (curproxy->conf.logformat_string) {
6297 curproxy->conf.args.ctx = ARGC_LOG;
6298 curproxy->conf.args.file = curproxy->conf.lfs_file;
6299 curproxy->conf.args.line = curproxy->conf.lfs_line;
6300 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006301 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006302 curproxy->conf.args.file = NULL;
6303 curproxy->conf.args.line = 0;
6304 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006305
Willy Tarreau62a61232013-04-12 18:13:46 +02006306 if (curproxy->conf.uniqueid_format_string) {
6307 curproxy->conf.args.ctx = ARGC_UIF;
6308 curproxy->conf.args.file = curproxy->conf.uif_file;
6309 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006310 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006311 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6312 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006313 curproxy->conf.args.file = NULL;
6314 curproxy->conf.args.line = 0;
6315 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006316
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006317 /* only now we can check if some args remain unresolved.
6318 * This must be done after the users and groups resolution.
6319 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006320 cfgerr += smp_resolve_args(curproxy);
6321 if (!cfgerr)
6322 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006323
Willy Tarreau2738a142006-07-08 17:28:09 +02006324 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006325 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006326 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006327 (!curproxy->timeout.connect ||
6328 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006329 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006330 " | While not properly invalid, you will certainly encounter various problems\n"
6331 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006332 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006333 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006334 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006335 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006336
Willy Tarreau1fa31262007-12-03 00:36:16 +01006337 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6338 * We must still support older configurations, so let's find out whether those
6339 * parameters have been set or must be copied from contimeouts.
6340 */
6341 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006342 if (!curproxy->timeout.tarpit ||
6343 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006344 /* tarpit timeout not set. We search in the following order:
6345 * default.tarpit, curr.connect, default.connect.
6346 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006347 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006348 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006349 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006350 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006351 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006352 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006353 }
6354 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006355 (!curproxy->timeout.queue ||
6356 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006357 /* queue timeout not set. We search in the following order:
6358 * default.queue, curr.connect, default.connect.
6359 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006360 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006361 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006362 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006363 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006364 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006365 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006366 }
6367 }
6368
Willy Tarreau1620ec32011-08-06 17:05:02 +02006369 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006370 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6371 curproxy->check_req = (char *)malloc(curproxy->check_len);
6372 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006373 }
6374
Willy Tarreau193b8c62012-11-22 00:17:38 +01006375 /* ensure that cookie capture length is not too large */
6376 if (curproxy->capture_len >= global.tune.cookie_len) {
6377 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6378 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6379 err_code |= ERR_WARN;
6380 curproxy->capture_len = global.tune.cookie_len - 1;
6381 }
6382
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006383 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006384 if (curproxy->nb_req_cap) {
6385 if (curproxy->mode == PR_MODE_HTTP) {
6386 curproxy->req_cap_pool = create_pool("ptrcap",
6387 curproxy->nb_req_cap * sizeof(char *),
6388 MEM_F_SHARED);
6389 } else {
6390 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6391 proxy_type_str(curproxy), curproxy->id);
6392 err_code |= ERR_WARN;
6393 curproxy->to_log &= ~LW_REQHDR;
6394 curproxy->nb_req_cap = 0;
6395 }
6396 }
6397
6398 if (curproxy->nb_rsp_cap) {
6399 if (curproxy->mode == PR_MODE_HTTP) {
6400 curproxy->rsp_cap_pool = create_pool("ptrcap",
6401 curproxy->nb_rsp_cap * sizeof(char *),
6402 MEM_F_SHARED);
6403 } else {
6404 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6405 proxy_type_str(curproxy), curproxy->id);
6406 err_code |= ERR_WARN;
6407 curproxy->to_log &= ~LW_REQHDR;
6408 curproxy->nb_rsp_cap = 0;
6409 }
6410 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006411
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 /* first, we will invert the servers list order */
6413 newsrv = NULL;
6414 while (curproxy->srv) {
6415 struct server *next;
6416
6417 next = curproxy->srv->next;
6418 curproxy->srv->next = newsrv;
6419 newsrv = curproxy->srv;
6420 if (!next)
6421 break;
6422 curproxy->srv = next;
6423 }
6424
Willy Tarreau17edc812014-01-03 12:14:34 +01006425 /* Check that no server name conflicts. This causes trouble in the stats.
6426 * We only emit a warning for the first conflict affecting each server,
6427 * in order to avoid combinatory explosion if all servers have the same
6428 * name. We do that only for servers which do not have an explicit ID,
6429 * because these IDs were made also for distinguishing them and we don't
6430 * want to annoy people who correctly manage them.
6431 */
6432 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6433 struct server *other_srv;
6434
6435 if (newsrv->puid)
6436 continue;
6437
6438 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6439 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6440 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6441 newsrv->conf.file, newsrv->conf.line,
6442 proxy_type_str(curproxy), curproxy->id,
6443 newsrv->id, other_srv->conf.line);
6444 break;
6445 }
6446 }
6447 }
6448
Willy Tarreaudd701652010-05-25 23:03:02 +02006449 /* assign automatic UIDs to servers which don't have one yet */
6450 next_id = 1;
6451 newsrv = curproxy->srv;
6452 while (newsrv != NULL) {
6453 if (!newsrv->puid) {
6454 /* server ID not set, use automatic numbering with first
6455 * spare entry starting with next_svid.
6456 */
6457 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6458 newsrv->conf.id.key = newsrv->puid = next_id;
6459 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6460 }
6461 next_id++;
6462 newsrv = newsrv->next;
6463 }
6464
Willy Tarreau20697042007-11-15 23:26:18 +01006465 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006466 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467
Willy Tarreau62c3be22012-01-20 13:12:32 +01006468 /*
6469 * If this server supports a maxconn parameter, it needs a dedicated
6470 * tasks to fill the emptied slots when a connection leaves.
6471 * Also, resolve deferred tracking dependency if needed.
6472 */
6473 newsrv = curproxy->srv;
6474 while (newsrv != NULL) {
6475 if (newsrv->minconn > newsrv->maxconn) {
6476 /* Only 'minconn' was specified, or it was higher than or equal
6477 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6478 * this will avoid further useless expensive computations.
6479 */
6480 newsrv->maxconn = newsrv->minconn;
6481 } else if (newsrv->maxconn && !newsrv->minconn) {
6482 /* minconn was not specified, so we set it to maxconn */
6483 newsrv->minconn = newsrv->maxconn;
6484 }
6485
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006486#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006487 if (newsrv->use_ssl || newsrv->check.use_ssl)
6488 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006489#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006490
Willy Tarreau2f075e92013-12-03 11:11:34 +01006491 /* set the check type on the server */
6492 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6493
Willy Tarreau62c3be22012-01-20 13:12:32 +01006494 if (newsrv->trackit) {
6495 struct proxy *px;
6496 struct server *srv;
6497 char *pname, *sname;
6498
6499 pname = newsrv->trackit;
6500 sname = strrchr(pname, '/');
6501
6502 if (sname)
6503 *sname++ = '\0';
6504 else {
6505 sname = pname;
6506 pname = NULL;
6507 }
6508
6509 if (pname) {
6510 px = findproxy(pname, PR_CAP_BE);
6511 if (!px) {
6512 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6513 proxy_type_str(curproxy), curproxy->id,
6514 newsrv->id, pname);
6515 cfgerr++;
6516 goto next_srv;
6517 }
6518 } else
6519 px = curproxy;
6520
6521 srv = findserver(px, sname);
6522 if (!srv) {
6523 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6524 proxy_type_str(curproxy), curproxy->id,
6525 newsrv->id, sname);
6526 cfgerr++;
6527 goto next_srv;
6528 }
6529
Willy Tarreauff5ae352013-12-11 20:36:34 +01006530 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006531 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6532 "tracking as it does not have checks enabled.\n",
6533 proxy_type_str(curproxy), curproxy->id,
6534 newsrv->id, px->id, srv->id);
6535 cfgerr++;
6536 goto next_srv;
6537 }
6538
6539 if (curproxy != px &&
6540 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6541 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6542 "tracking: disable-on-404 option inconsistency.\n",
6543 proxy_type_str(curproxy), curproxy->id,
6544 newsrv->id, px->id, srv->id);
6545 cfgerr++;
6546 goto next_srv;
6547 }
6548
6549 /* if the other server is forced disabled, we have to do the same here */
6550 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006551 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09006552 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09006553 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006554 }
6555
6556 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006557 newsrv->tracknext = srv->trackers;
6558 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006559
6560 free(newsrv->trackit);
6561 newsrv->trackit = NULL;
6562 }
6563 next_srv:
6564 newsrv = newsrv->next;
6565 }
6566
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006567 /* We have to initialize the server lookup mechanism depending
6568 * on what LB algorithm was choosen.
6569 */
6570
6571 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6572 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6573 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006574 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6575 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6576 init_server_map(curproxy);
6577 } else {
6578 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6579 fwrr_init_server_groups(curproxy);
6580 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006581 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006582
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006583 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006584 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6585 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6586 fwlc_init_server_tree(curproxy);
6587 } else {
6588 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6589 fas_init_server_tree(curproxy);
6590 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006591 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006592
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006593 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006594 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6595 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6596 chash_init_server_tree(curproxy);
6597 } else {
6598 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6599 init_server_map(curproxy);
6600 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006601 break;
6602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603
6604 if (curproxy->options & PR_O_LOGASAP)
6605 curproxy->to_log &= ~LW_BYTES;
6606
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006607 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006608 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006609 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6610 proxy_type_str(curproxy), curproxy->id);
6611 err_code |= ERR_WARN;
6612 }
6613
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006614 if (curproxy->mode != PR_MODE_HTTP) {
6615 int optnum;
6616
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006617 if (curproxy->uri_auth) {
6618 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6619 proxy_type_str(curproxy), curproxy->id);
6620 err_code |= ERR_WARN;
6621 curproxy->uri_auth = NULL;
6622 }
6623
Willy Tarreau87cf5142011-08-19 22:57:24 +02006624 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006625 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6626 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6627 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006628 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006629 }
6630
6631 if (curproxy->options & PR_O_ORGTO) {
6632 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6633 "originalto", proxy_type_str(curproxy), curproxy->id);
6634 err_code |= ERR_WARN;
6635 curproxy->options &= ~PR_O_ORGTO;
6636 }
6637
6638 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6639 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6640 (curproxy->cap & cfg_opts[optnum].cap) &&
6641 (curproxy->options & cfg_opts[optnum].val)) {
6642 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6643 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6644 err_code |= ERR_WARN;
6645 curproxy->options &= ~cfg_opts[optnum].val;
6646 }
6647 }
6648
6649 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6650 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6651 (curproxy->cap & cfg_opts2[optnum].cap) &&
6652 (curproxy->options2 & cfg_opts2[optnum].val)) {
6653 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6654 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6655 err_code |= ERR_WARN;
6656 curproxy->options2 &= ~cfg_opts2[optnum].val;
6657 }
6658 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006659
Pieter Baauwd551fb52013-05-08 22:49:23 +02006660#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006661 if (curproxy->conn_src.bind_hdr_occ) {
6662 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006663 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006664 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006665 err_code |= ERR_WARN;
6666 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006667#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006668 }
6669
Willy Tarreaubaaee002006-06-26 02:48:02 +02006670 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006671 * ensure that we're not cross-dressing a TCP server into HTTP.
6672 */
6673 newsrv = curproxy->srv;
6674 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006675 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006676 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6677 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006678 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006679 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006680
Willy Tarreau0cec3312011-10-31 13:49:26 +01006681 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6682 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6683 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6684 err_code |= ERR_WARN;
6685 }
6686
Willy Tarreau82ffa392013-08-13 17:19:08 +02006687 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6688 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6689 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6690 err_code |= ERR_WARN;
6691 }
6692
Pieter Baauwd551fb52013-05-08 22:49:23 +02006693#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006694 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6695 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006696 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 +01006697 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006698 err_code |= ERR_WARN;
6699 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006700#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006701 newsrv = newsrv->next;
6702 }
6703
Willy Tarreauc1a21672009-08-16 22:37:44 +02006704 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006705 if (!curproxy->accept)
6706 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006707
Willy Tarreauc1a21672009-08-16 22:37:44 +02006708 if (curproxy->tcp_req.inspect_delay ||
6709 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006710 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006711
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006712 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006713 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006714 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006715 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006716
6717 /* both TCP and HTTP must check switching rules */
6718 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6719 }
6720
6721 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006722 if (curproxy->tcp_req.inspect_delay ||
6723 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6724 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6725
Emeric Brun97679e72010-09-23 17:56:44 +02006726 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6727 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6728
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006729 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006730 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006731 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006732 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006733
6734 /* If the backend does requires RDP cookie persistence, we have to
6735 * enable the corresponding analyser.
6736 */
6737 if (curproxy->options2 & PR_O2_RDPC_PRST)
6738 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6739 }
6740
Emeric Brunc52962f2012-11-15 18:28:02 +01006741#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006742 /* Configure SSL for each bind line.
6743 * Note: if configuration fails at some point, the ->ctx member
6744 * remains NULL so that listeners can later detach.
6745 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006746 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006747 if (!bind_conf->is_ssl) {
6748 if (bind_conf->default_ctx) {
6749 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6750 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6751 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006752 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006753 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006754 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006755 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006756 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006757 cfgerr++;
6758 continue;
6759 }
6760
Emeric Brun4b3091e2012-09-24 15:48:52 +02006761 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006762 Alert("Unable to allocate SSL session cache.\n");
6763 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006764 continue;
6765 }
6766
Emeric Brunfc0421f2012-09-07 17:30:07 +02006767 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006768 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006769 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006770#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006771
Willy Tarreaue6b98942007-10-29 01:09:36 +01006772 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006773 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006774 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006775 if (!listener->luid) {
6776 /* listener ID not set, use automatic numbering with first
6777 * spare entry starting with next_luid.
6778 */
6779 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6780 listener->conf.id.key = listener->luid = next_id;
6781 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006782 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006783 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006784
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006785 /* enable separate counters */
6786 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6787 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006788 if (!listener->name)
6789 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006790 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006791
Willy Tarreaue6b98942007-10-29 01:09:36 +01006792 if (curproxy->options & PR_O_TCP_NOLING)
6793 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006794 if (!listener->maxconn)
6795 listener->maxconn = curproxy->maxconn;
6796 if (!listener->backlog)
6797 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006798 if (!listener->maxaccept)
6799 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6800
6801 /* we want to have an optimal behaviour on single process mode to
6802 * maximize the work at once, but in multi-process we want to keep
6803 * some fairness between processes, so we target half of the max
6804 * number of events to be balanced over all the processes the proxy
6805 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6806 * used to disable the limit.
6807 */
6808 if (listener->maxaccept > 0) {
6809 if (nbproc > 1)
6810 listener->maxaccept = (listener->maxaccept + 1) / 2;
6811 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6812 }
6813
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006814 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006815 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006816 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006817 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006818
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006819 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6820 listener->options |= LI_O_TCP_RULES;
6821
Willy Tarreaude3041d2010-05-31 10:56:17 +02006822 if (curproxy->mon_mask.s_addr)
6823 listener->options |= LI_O_CHK_MONNET;
6824
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006825 /* smart accept mode is automatic in HTTP mode */
6826 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006827 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006828 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6829 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006830 }
6831
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006832 /* Release unused SSL configs */
6833 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6834 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006835 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006836#ifdef USE_OPENSSL
6837 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006838 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006839 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006840 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006841 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006842#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006843 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006844
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006845 /* Check multi-process mode compatibility for the current proxy */
6846 if (global.nbproc > 1) {
6847 int nbproc = 0;
6848 if (curproxy->bind_proc) {
6849 int proc;
6850 for (proc = 0; proc < global.nbproc; proc++) {
6851 if (curproxy->bind_proc & (1 << proc)) {
6852 nbproc++;
6853 }
6854 }
6855 } else {
6856 nbproc = global.nbproc;
6857 }
6858 if (curproxy->table.peers.name) {
6859 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6860 curproxy->id);
6861 cfgerr++;
6862 }
6863 if (nbproc > 1) {
6864 if (curproxy->uri_auth) {
6865 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6866 curproxy->id);
6867 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6868 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6869 curproxy->id);
6870 }
6871 }
6872 if (curproxy->appsession_name) {
6873 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6874 curproxy->id);
6875 }
6876 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6877 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6878 curproxy->id);
6879 }
6880 }
6881 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006882
6883 /* create the task associated with the proxy */
6884 curproxy->task = task_new();
6885 if (curproxy->task) {
6886 curproxy->task->context = curproxy;
6887 curproxy->task->process = manage_proxy;
6888 /* no need to queue, it will be done automatically if some
6889 * listener gets limited.
6890 */
6891 curproxy->task->expire = TICK_ETERNITY;
6892 } else {
6893 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6894 curproxy->id);
6895 cfgerr++;
6896 }
6897
Willy Tarreaubaaee002006-06-26 02:48:02 +02006898 curproxy = curproxy->next;
6899 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006900
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006901 /* Check multi-process mode compatibility */
6902 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006903 if (global.stats_fe && !global.stats_fe->bind_proc) {
6904 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 +01006905 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006906 }
6907
6908 /* automatically compute fullconn if not set. We must not do it in the
6909 * loop above because cross-references are not yet fully resolved.
6910 */
6911 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6912 /* If <fullconn> is not set, let's set it to 10% of the sum of
6913 * the possible incoming frontend's maxconns.
6914 */
6915 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6916 struct proxy *fe;
6917 int total = 0;
6918
6919 /* sum up the number of maxconns of frontends which
6920 * reference this backend at least once or which are
6921 * the same one ('listen').
6922 */
6923 for (fe = proxy; fe; fe = fe->next) {
6924 struct switching_rule *rule;
6925 struct hdr_exp *exp;
6926 int found = 0;
6927
6928 if (!(fe->cap & PR_CAP_FE))
6929 continue;
6930
6931 if (fe == curproxy) /* we're on a "listen" instance */
6932 found = 1;
6933
6934 if (fe->defbe.be == curproxy) /* "default_backend" */
6935 found = 1;
6936
6937 /* check if a "use_backend" rule matches */
6938 if (!found) {
6939 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006940 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02006941 found = 1;
6942 break;
6943 }
6944 }
6945 }
6946
6947 /* check if a "reqsetbe" rule matches */
6948 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6949 if (exp->action == ACT_SETBE &&
6950 (struct proxy *)exp->replace == curproxy) {
6951 found = 1;
6952 break;
6953 }
6954 }
6955
6956 /* now we've checked all possible ways to reference a backend
6957 * from a frontend.
6958 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006959 if (!found)
6960 continue;
6961 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006962 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006963 /* we have the sum of the maxconns in <total>. We only
6964 * keep 10% of that sum to set the default fullconn, with
6965 * a hard minimum of 1 (to avoid a divide by zero).
6966 */
6967 curproxy->fullconn = (total + 9) / 10;
6968 if (!curproxy->fullconn)
6969 curproxy->fullconn = 1;
6970 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006971 }
6972
Willy Tarreau056f5682010-06-06 15:51:11 +02006973 /* initialize stick-tables on backend capable proxies. This must not
6974 * be done earlier because the data size may be discovered while parsing
6975 * other proxies.
6976 */
Godbach9703e662013-12-11 21:11:41 +08006977 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01006978 if (curproxy->state == PR_STSTOPPED)
6979 continue;
6980
Godbach9703e662013-12-11 21:11:41 +08006981 if (!stktable_init(&curproxy->table)) {
6982 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
6983 cfgerr++;
6984 }
6985 }
Willy Tarreau056f5682010-06-06 15:51:11 +02006986
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006987 /*
6988 * Recount currently required checks.
6989 */
6990
6991 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6992 int optnum;
6993
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006994 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6995 if (curproxy->options & cfg_opts[optnum].val)
6996 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006997
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006998 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6999 if (curproxy->options2 & cfg_opts2[optnum].val)
7000 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007001 }
7002
Willy Tarreau122541c2011-09-07 21:24:49 +02007003 if (peers) {
7004 struct peers *curpeers = peers, **last;
7005 struct peer *p, *pb;
7006
7007 /* Remove all peers sections which don't have a valid listener.
7008 * This can happen when a peers section is never referenced and
7009 * does not contain a local peer.
7010 */
7011 last = &peers;
7012 while (*last) {
7013 curpeers = *last;
7014 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007015 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007016 last = &curpeers->next;
7017 continue;
7018 }
7019
7020 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7021 curpeers->id, localpeer);
7022
7023 p = curpeers->remote;
7024 while (p) {
7025 pb = p->next;
7026 free(p->id);
7027 free(p);
7028 p = pb;
7029 }
7030
7031 /* Destroy and unlink this curpeers section.
7032 * Note: curpeers is backed up into *last.
7033 */
7034 free(curpeers->id);
7035 curpeers = curpeers->next;
7036 free(*last);
7037 *last = curpeers;
7038 }
7039 }
7040
Willy Tarreau34eb6712011-10-24 18:15:04 +02007041 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007042 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007043 MEM_F_SHARED);
7044
Willy Tarreaubb925012009-07-23 13:36:36 +02007045 if (cfgerr > 0)
7046 err_code |= ERR_ALERT | ERR_FATAL;
7047 out:
7048 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049}
7050
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007051/*
7052 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7053 * parsing sessions.
7054 */
7055void cfg_register_keywords(struct cfg_kw_list *kwl)
7056{
7057 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7058}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007060/*
7061 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7062 */
7063void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7064{
7065 LIST_DEL(&kwl->list);
7066 LIST_INIT(&kwl->list);
7067}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007068
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007069/* this function register new section in the haproxy configuration file.
7070 * <section_name> is the name of this new section and <section_parser>
7071 * is the called parser. If two section declaration have the same name,
7072 * only the first declared is used.
7073 */
7074int cfg_register_section(char *section_name,
7075 int (*section_parser)(const char *, int, char **, int))
7076{
7077 struct cfg_section *cs;
7078
7079 cs = calloc(1, sizeof(*cs));
7080 if (!cs) {
7081 Alert("register section '%s': out of memory.\n", section_name);
7082 return 0;
7083 }
7084
7085 cs->section_name = section_name;
7086 cs->section_parser = section_parser;
7087
7088 LIST_ADDQ(&sections, &cs->list);
7089
7090 return 1;
7091}
7092
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093/*
7094 * Local variables:
7095 * c-indent-level: 8
7096 * c-basic-offset: 8
7097 * End:
7098 */