blob: e433c2c275ddee4609158b91f6510f8563214611 [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 Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100114/* permit to store configuration section */
115struct cfg_section {
116 struct list list;
117 char *section_name;
118 int (*section_parser)(const char *, int, char **, int);
119};
120
121/* Used to chain configuration sections definitions. This list
122 * stores struct cfg_section
123 */
124struct list sections = LIST_HEAD_INIT(sections);
125
Willy Tarreau13943ab2006-12-31 00:24:10 +0100126/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100127struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100128 const char *name;
129 unsigned int val;
130 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100131 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100133};
134
135/* proxy->options */
136static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
139 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
140 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
141 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
142 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
143 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100145 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
147 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
148 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
149 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
150 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100151#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100153#else
154 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100155#endif
156
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100158};
159
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100160/* proxy->options2 */
161static const struct cfg_opt cfg_opts2[] =
162{
163#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
165 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
166 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "splice-request", 0, 0, 0, 0 },
169 { "splice-response", 0, 0, 0, 0 },
170 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100171#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
173 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
174 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
175 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
176 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
177 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
178 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
179 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
180 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400181 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200183 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200184 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185 { NULL, 0, 0, 0 }
186};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187
Willy Tarreau6daf3432008-01-22 16:44:08 +0100188static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
190int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100191int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200193/* List head of all known configuration keywords */
194static struct cfg_kw_list cfg_keywords = {
195 .list = LIST_HEAD_INIT(cfg_keywords.list)
196};
197
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198/*
199 * converts <str> to a list of listeners which are dynamically allocated.
200 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
201 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
202 * - <port> is a numerical port from 1 to 65535 ;
203 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
204 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200205 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
206 * not NULL, it must be a valid pointer to either NULL or a freeable area that
207 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200209int 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 +0200210{
211 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100212 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 int port, end;
214
215 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100219 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220
221 str = next;
222 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100223 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 *next++ = 0;
225 }
226
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100227 ss2 = str2sa_range(str, &port, &end, err,
228 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
229 if (!ss2)
230 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100233 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100235 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100238 if (!port || !end) {
239 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
240 goto fail;
241 }
242
Emeric Bruned760922010-10-22 17:59:25 +0200243 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200245 goto fail;
246 }
247
248 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200250 goto fail;
251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100253 else if (ss2->ss_family == AF_UNSPEC) {
254 socklen_t addr_len;
255
256 /* We want to attach to an already bound fd whose number
257 * is in the addr part of ss2 when cast to sockaddr_in.
258 * Note that by definition there is a single listener.
259 * We still have to determine the address family to
260 * register the correct protocol.
261 */
262 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
263 addr_len = sizeof(*ss2);
264 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
265 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
266 goto fail;
267 }
268
269 port = end = get_host_port(ss2);
270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100272 /* OK the address looks correct */
273 ss = *ss2;
274
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 for (; port <= end; port++) {
276 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100277 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200278 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
279 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
280 l->frontend = curproxy;
281 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282
Willy Tarreau40aa0702013-03-10 23:51:38 +0100283 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200285 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100286 l->state = LI_INIT;
287
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100288 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100290 tcpv4_add_listener(l);
291 }
Emeric Bruned760922010-10-22 17:59:25 +0200292 else if (ss.ss_family == AF_INET6) {
293 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
294 tcpv6_add_listener(l);
295 }
296 else {
Emeric Bruned760922010-10-22 17:59:25 +0200297 uxst_add_listener(l);
298 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200300 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 } /* end for(port) */
303 } /* end while(next) */
304 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200305 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 fail:
307 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200308 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309}
310
Willy Tarreau977b8e42006-12-29 14:19:17 +0100311/*
312 * Sends a warning if proxy <proxy> does not have at least one of the
313 * capabilities in <cap>. An optionnal <hint> may be added at the end
314 * of the warning to help the user. Returns 1 if a warning was emitted
315 * or 0 if the condition is valid.
316 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100317int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100318{
319 char *msg;
320
321 switch (cap) {
322 case PR_CAP_BE: msg = "no backend"; break;
323 case PR_CAP_FE: msg = "no frontend"; break;
324 case PR_CAP_RS: msg = "no ruleset"; break;
325 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
326 default: msg = "not enough"; break;
327 }
328
329 if (!(proxy->cap & cap)) {
330 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100331 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100332 return 1;
333 }
334 return 0;
335}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200336
Willy Tarreau61d18892009-03-31 10:49:21 +0200337/* Report a warning if a rule is placed after a 'block' rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100340int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200341{
342 if (!LIST_ISEMPTY(&proxy->block_cond)) {
343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
350/* Report a warning if a rule is placed after a reqrewrite rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100353int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200354{
355 if (proxy->req_exp) {
356 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
363/* Report a warning if a rule is placed after a reqadd rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100366int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200367{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100368 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
376/* Report a warning if a rule is placed after a redirect rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
381 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
389/* Report a warning if a rule is placed after a 'use_backend' rule.
390 * Return 1 if the warning has been emitted, otherwise 0.
391 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
395 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
396 file, line, arg);
397 return 1;
398 }
399 return 0;
400}
401
402/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return 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) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
415 warnif_rule_after_redirect(proxy, file, line, arg) ||
416 warnif_rule_after_use_backend(proxy, file, line, arg);
417}
418
419/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100420int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200421{
422 return warnif_rule_after_redirect(proxy, file, line, arg) ||
423 warnif_rule_after_use_backend(proxy, file, line, arg);
424}
425
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100426/* Report it if a request ACL condition uses some keywords that are incompatible
427 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
428 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
429 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100430 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100431static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100432{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100433 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200434 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100435
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100436 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100437 return 0;
438
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100439 acl = acl_cond_conflicts(cond, where);
440 if (acl) {
441 if (acl->name && *acl->name)
442 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
443 file, line, acl->name, sample_ckp_names(where));
444 else
445 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 +0200446 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100447 return ERR_WARN;
448 }
449 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100450 return 0;
451
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100452 if (acl->name && *acl->name)
453 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200454 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100455 else
456 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200457 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100458 return ERR_WARN;
459}
460
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200462 * parse a line in a <global> section. Returns the error code, 0 if OK, or
463 * any combination of :
464 * - ERR_ABORT: must abort ASAP
465 * - ERR_FATAL: we can continue parsing but not start the service
466 * - ERR_WARN: a warning has been emitted
467 * - ERR_ALERT: an alert has been emitted
468 * Only the two first ones can stop processing, the two others are just
469 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200471int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472{
Willy Tarreau058e9072009-07-20 09:30:05 +0200473 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200474 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475
476 if (!strcmp(args[0], "global")) { /* new section */
477 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200480 else if (!strcmp(args[0], "ca-base")) {
481#ifdef USE_OPENSSL
482 if (global.ca_base != NULL) {
483 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
484 err_code |= ERR_ALERT;
485 goto out;
486 }
487 if (*(args[1]) == 0) {
488 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
489 err_code |= ERR_ALERT | ERR_FATAL;
490 goto out;
491 }
492 global.ca_base = strdup(args[1]);
493#else
494 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT | ERR_FATAL;
496 goto out;
497#endif
498 }
499 else if (!strcmp(args[0], "crt-base")) {
500#ifdef USE_OPENSSL
501 if (global.crt_base != NULL) {
502 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
503 err_code |= ERR_ALERT;
504 goto out;
505 }
506 if (*(args[1]) == 0) {
507 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
508 err_code |= ERR_ALERT | ERR_FATAL;
509 goto out;
510 }
511 global.crt_base = strdup(args[1]);
512#else
513 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT | ERR_FATAL;
515 goto out;
516#endif
517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "daemon")) {
519 global.mode |= MODE_DAEMON;
520 }
521 else if (!strcmp(args[0], "debug")) {
522 global.mode |= MODE_DEBUG;
523 }
524 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100525 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200527 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100528 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100531 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200532 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100533 else if (!strcmp(args[0], "nosplice")) {
534 global.tune.options &= ~GTUNE_USE_SPLICE;
535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200536 else if (!strcmp(args[0], "quiet")) {
537 global.mode |= MODE_QUIET;
538 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200539 else if (!strcmp(args[0], "tune.maxpollevents")) {
540 if (global.tune.maxpollevents != 0) {
541 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 err_code |= ERR_ALERT;
543 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200544 }
545 if (*(args[1]) == 0) {
546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT | ERR_FATAL;
548 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200549 }
550 global.tune.maxpollevents = atol(args[1]);
551 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100552 else if (!strcmp(args[0], "tune.maxaccept")) {
553 if (global.tune.maxaccept != 0) {
554 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200555 err_code |= ERR_ALERT;
556 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100557 }
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100562 }
563 global.tune.maxaccept = atol(args[1]);
564 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200565 else if (!strcmp(args[0], "tune.chksize")) {
566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.chksize = atol(args[1]);
572 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200573#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100574 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.tune.sslcachesize = atol(args[1]);
581 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100582 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
583 unsigned int ssllifetime;
584 const char *res;
585
586 if (*(args[1]) == 0) {
587 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
593 if (res) {
594 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
595 file, linenum, *res, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599
600 global.tune.ssllifetime = ssllifetime;
601 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100602 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.ssl_max_record = atol(args[1]);
609 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200610#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200611 else if (!strcmp(args[0], "tune.bufsize")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.bufsize = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100620 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100621 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200622 }
623 else if (!strcmp(args[0], "tune.maxrewrite")) {
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
628 }
629 global.tune.maxrewrite = atol(args[1]);
630 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
631 global.tune.maxrewrite = global.tune.bufsize / 2;
632 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100633 else if (!strcmp(args[0], "tune.idletimer")) {
634 unsigned int idle;
635 const char *res;
636
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
641 }
642
643 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
644 if (res) {
645 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
646 file, linenum, *res, args[0]);
647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
649 }
650
651 if (idle > 65535) {
652 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.idle_timer = idle;
657 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100658 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
659 if (global.tune.client_rcvbuf != 0) {
660 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
661 err_code |= ERR_ALERT;
662 goto out;
663 }
664 if (*(args[1]) == 0) {
665 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
666 err_code |= ERR_ALERT | ERR_FATAL;
667 goto out;
668 }
669 global.tune.client_rcvbuf = atol(args[1]);
670 }
671 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
672 if (global.tune.server_rcvbuf != 0) {
673 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
674 err_code |= ERR_ALERT;
675 goto out;
676 }
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.server_rcvbuf = atol(args[1]);
683 }
684 else if (!strcmp(args[0], "tune.sndbuf.client")) {
685 if (global.tune.client_sndbuf != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT;
688 goto out;
689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.client_sndbuf = atol(args[1]);
696 }
697 else if (!strcmp(args[0], "tune.sndbuf.server")) {
698 if (global.tune.server_sndbuf != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT;
701 goto out;
702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708 global.tune.server_sndbuf = atol(args[1]);
709 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200710 else if (!strcmp(args[0], "tune.pipesize")) {
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 global.tune.pipesize = atol(args[1]);
717 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100718 else if (!strcmp(args[0], "tune.http.cookielen")) {
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.tune.cookie_len = atol(args[1]) + 1;
725 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200726 else if (!strcmp(args[0], "tune.http.maxhdr")) {
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 global.tune.max_http_hdr = atol(args[1]);
733 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100734 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
735#ifdef USE_ZLIB
736 if (*args[1]) {
737 global.tune.zlibmemlevel = atoi(args[1]);
738 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
739 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
740 file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 } else {
745 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
746 file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750#else
751 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754#endif
755 }
756 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
757#ifdef USE_ZLIB
758 if (*args[1]) {
759 global.tune.zlibwindowsize = atoi(args[1]);
760 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
761 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
762 file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 } else {
767 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
768 file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772#else
773 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
774 err_code |= ERR_ALERT | ERR_FATAL;
775 goto out;
776#endif
777 }
William Lallemandf3747832012-11-09 12:33:10 +0100778 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
779 if (*args[1]) {
780 global.tune.comp_maxlevel = atoi(args[1]);
781 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
782 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
783 file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787 } else {
788 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
789 file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 else if (!strcmp(args[0], "uid")) {
795 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200796 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200797 err_code |= ERR_ALERT;
798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200799 }
800 if (*(args[1]) == 0) {
801 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200804 }
805 global.uid = atol(args[1]);
806 }
807 else if (!strcmp(args[0], "gid")) {
808 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 if (*(args[1]) == 0) {
814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 global.gid = atol(args[1]);
819 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200820 /* user/group name handling */
821 else if (!strcmp(args[0], "user")) {
822 struct passwd *ha_user;
823 if (global.uid != 0) {
824 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT;
826 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200827 }
828 errno = 0;
829 ha_user = getpwnam(args[1]);
830 if (ha_user != NULL) {
831 global.uid = (int)ha_user->pw_uid;
832 }
833 else {
834 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 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200836 }
837 }
838 else if (!strcmp(args[0], "group")) {
839 struct group *ha_group;
840 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200841 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200842 err_code |= ERR_ALERT;
843 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200844 }
845 errno = 0;
846 ha_group = getgrnam(args[1]);
847 if (ha_group != NULL) {
848 global.gid = (int)ha_group->gr_gid;
849 }
850 else {
851 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 +0200852 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200853 }
854 }
855 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200856 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 if (*(args[1]) == 0) {
858 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 }
862 global.nbproc = atol(args[1]);
863 }
864 else if (!strcmp(args[0], "maxconn")) {
865 if (global.maxconn != 0) {
866 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200867 err_code |= ERR_ALERT;
868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 }
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874 }
875 global.maxconn = atol(args[1]);
876#ifdef SYSTEM_MAXCONN
877 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
878 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);
879 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881 }
882#endif /* SYSTEM_MAXCONN */
883 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200884 else if (!strcmp(args[0], "maxsslconn")) {
885#ifdef USE_OPENSSL
886 if (*(args[1]) == 0) {
887 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.maxsslconn = atol(args[1]);
892#else
Emeric Brun0914df82012-10-02 18:45:42 +0200893 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200896#endif
897 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100898 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
899#ifdef USE_OPENSSL
900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905 free(global.listen_default_ciphers);
906 global.listen_default_ciphers = strdup(args[1]);
907#else
908 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911#endif
912 }
913 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
914#ifdef USE_OPENSSL
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
919 }
920 free(global.connect_default_ciphers);
921 global.connect_default_ciphers = strdup(args[1]);
922#else
923 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
924 err_code |= ERR_ALERT | ERR_FATAL;
925 goto out;
926#endif
927 }
Emeric Brun850efd52014-01-29 12:24:34 +0100928 else if (!strcmp(args[0], "ssl-server-verify")) {
929 if (*(args[1]) == 0) {
930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
931 err_code |= ERR_ALERT | ERR_FATAL;
932 goto out;
933 }
934 if (strcmp(args[1],"none") == 0)
935 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
936 else if (strcmp(args[1],"required") == 0)
937 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
938 else {
939 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200944 else if (!strcmp(args[0], "maxconnrate")) {
945 if (global.cps_lim != 0) {
946 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT;
948 goto out;
949 }
950 if (*(args[1]) == 0) {
951 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955 global.cps_lim = atol(args[1]);
956 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200957 else if (!strcmp(args[0], "maxsessrate")) {
958 if (global.sps_lim != 0) {
959 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
960 err_code |= ERR_ALERT;
961 goto out;
962 }
963 if (*(args[1]) == 0) {
964 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
965 err_code |= ERR_ALERT | ERR_FATAL;
966 goto out;
967 }
968 global.sps_lim = atol(args[1]);
969 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200970 else if (!strcmp(args[0], "maxsslrate")) {
971 if (global.ssl_lim != 0) {
972 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
973 err_code |= ERR_ALERT;
974 goto out;
975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.ssl_lim = atol(args[1]);
982 }
William Lallemandd85f9172012-11-09 17:05:39 +0100983 else if (!strcmp(args[0], "maxcomprate")) {
984 if (*(args[1]) == 0) {
985 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989 global.comp_rate_lim = atoi(args[1]) * 1024;
990 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100991 else if (!strcmp(args[0], "maxpipes")) {
992 if (global.maxpipes != 0) {
993 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT;
995 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100996 }
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001001 }
1002 global.maxpipes = atol(args[1]);
1003 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001004 else if (!strcmp(args[0], "maxzlibmem")) {
1005 if (*(args[1]) == 0) {
1006 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009 }
William Lallemande3a7d992012-11-20 11:25:20 +01001010 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001011 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001012 else if (!strcmp(args[0], "maxcompcpuusage")) {
1013 if (*(args[1]) == 0) {
1014 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1015 err_code |= ERR_ALERT | ERR_FATAL;
1016 goto out;
1017 }
1018 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001019 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001020 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024}
1025
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 else if (!strcmp(args[0], "ulimit-n")) {
1027 if (global.rlimit_nofile != 0) {
1028 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT;
1030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 }
1032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 }
1037 global.rlimit_nofile = atol(args[1]);
1038 }
1039 else if (!strcmp(args[0], "chroot")) {
1040 if (global.chroot != NULL) {
1041 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT;
1043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001044 }
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 }
1050 global.chroot = strdup(args[1]);
1051 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001052 else if (!strcmp(args[0], "description")) {
1053 int i, len=0;
1054 char *d;
1055
1056 if (!*args[1]) {
1057 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1058 file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062
1063 for(i=1; *args[i]; i++)
1064 len += strlen(args[i])+1;
1065
1066 if (global.desc)
1067 free(global.desc);
1068
1069 global.desc = d = (char *)calloc(1, len);
1070
1071 d += sprintf(d, "%s", args[1]);
1072 for(i=2; *args[i]; i++)
1073 d += sprintf(d, " %s", args[i]);
1074 }
1075 else if (!strcmp(args[0], "node")) {
1076 int i;
1077 char c;
1078
1079 for (i=0; args[1][i]; i++) {
1080 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001081 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1082 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001083 break;
1084 }
1085
1086 if (!i || args[1][i]) {
1087 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1088 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1089 file, linenum, args[0]);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093
1094 if (global.node)
1095 free(global.node);
1096
1097 global.node = strdup(args[1]);
1098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 else if (!strcmp(args[0], "pidfile")) {
1100 if (global.pidfile != NULL) {
1101 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT;
1103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
1110 global.pidfile = strdup(args[1]);
1111 }
Emeric Bruned760922010-10-22 17:59:25 +02001112 else if (!strcmp(args[0], "unix-bind")) {
1113 int cur_arg = 1;
1114 while (*(args[cur_arg])) {
1115 if (!strcmp(args[cur_arg], "prefix")) {
1116 if (global.unix_bind.prefix != NULL) {
1117 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1118 err_code |= ERR_ALERT;
1119 cur_arg += 2;
1120 continue;
1121 }
1122
1123 if (*(args[cur_arg+1]) == 0) {
1124 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1129 cur_arg += 2;
1130 continue;
1131 }
1132
1133 if (!strcmp(args[cur_arg], "mode")) {
1134
1135 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1136 cur_arg += 2;
1137 continue;
1138 }
1139
1140 if (!strcmp(args[cur_arg], "uid")) {
1141
1142 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1143 cur_arg += 2;
1144 continue;
1145 }
1146
1147 if (!strcmp(args[cur_arg], "gid")) {
1148
1149 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1150 cur_arg += 2;
1151 continue;
1152 }
1153
1154 if (!strcmp(args[cur_arg], "user")) {
1155 struct passwd *user;
1156
1157 user = getpwnam(args[cur_arg + 1]);
1158 if (!user) {
1159 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1160 file, linenum, args[0], args[cur_arg + 1 ]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
1164
1165 global.unix_bind.ux.uid = user->pw_uid;
1166 cur_arg += 2;
1167 continue;
1168 }
1169
1170 if (!strcmp(args[cur_arg], "group")) {
1171 struct group *group;
1172
1173 group = getgrnam(args[cur_arg + 1]);
1174 if (!group) {
1175 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1176 file, linenum, args[0], args[cur_arg + 1 ]);
1177 err_code |= ERR_ALERT | ERR_FATAL;
1178 goto out;
1179 }
1180
1181 global.unix_bind.ux.gid = group->gr_gid;
1182 cur_arg += 2;
1183 continue;
1184 }
1185
Willy Tarreaub48f9582011-09-05 01:17:06 +02001186 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001187 file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190 }
1191 }
William Lallemand0f99e342011-10-12 17:50:54 +02001192 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1193 /* delete previous herited or defined syslog servers */
1194 struct logsrv *back;
1195 struct logsrv *tmp;
1196
1197 if (*(args[1]) != 0) {
1198 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
1201 }
1202
1203 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1204 LIST_DEL(&tmp->list);
1205 free(tmp);
1206 }
1207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001209 struct sockaddr_storage *sk;
1210 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001211 struct logsrv *logsrv;
1212
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 if (*(args[1]) == 0 || *(args[2]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
William Lallemand0f99e342011-10-12 17:50:54 +02001218
1219 logsrv = calloc(1, sizeof(struct logsrv));
1220
1221 logsrv->facility = get_log_facility(args[2]);
1222 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001224 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001225 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001226 }
1227
William Lallemand0f99e342011-10-12 17:50:54 +02001228 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001230 logsrv->level = get_log_level(args[3]);
1231 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001233 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001234 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235 }
1236 }
1237
William Lallemand0f99e342011-10-12 17:50:54 +02001238 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001239 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001240 logsrv->minlvl = get_log_level(args[4]);
1241 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001242 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001243 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001244 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001245 }
1246 }
1247
Willy Tarreau902636f2013-03-10 19:44:48 +01001248 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001249 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001250 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001251 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001252 free(logsrv);
1253 goto out;
1254 }
1255 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001256
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001257 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001258 if (port1 != port2) {
1259 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1260 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001261 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001262 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001263 goto out;
1264 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001265
William Lallemand0f99e342011-10-12 17:50:54 +02001266 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001267 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001268 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001270
William Lallemand0f99e342011-10-12 17:50:54 +02001271 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001272 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001273 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1274 char *name;
1275 int len;
1276
1277 if (global.log_send_hostname != NULL) {
1278 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT;
1280 goto out;
1281 }
1282
1283 if (*(args[1]))
1284 name = args[1];
1285 else
1286 name = hostname;
1287
1288 len = strlen(name);
1289
1290 /* We'll add a space after the name to respect the log format */
1291 free(global.log_send_hostname);
1292 global.log_send_hostname = malloc(len + 2);
1293 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1294 }
Kevinm48936af2010-12-22 16:08:21 +00001295 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1296 if (*(args[1]) == 0) {
1297 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 free(global.log_tag);
1302 global.log_tag = strdup(args[1]);
1303 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001304 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1305 if (global.spread_checks != 0) {
1306 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001307 err_code |= ERR_ALERT;
1308 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001309 }
1310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001314 }
1315 global.spread_checks = atol(args[1]);
1316 if (global.spread_checks < 0 || global.spread_checks > 50) {
1317 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001318 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001321 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1322#ifdef USE_CPU_AFFINITY
1323 int cur_arg, i;
1324 unsigned int proc = 0;
1325 unsigned long cpus = 0;
1326
1327 if (strcmp(args[1], "all") == 0)
1328 proc = 0xFFFFFFFF;
1329 else if (strcmp(args[1], "odd") == 0)
1330 proc = 0x55555555;
1331 else if (strcmp(args[1], "even") == 0)
1332 proc = 0xAAAAAAAA;
1333 else {
1334 proc = atoi(args[1]);
1335 if (proc >= 1 && proc <= 32)
1336 proc = 1 << (proc - 1);
1337 }
1338
1339 if (!proc || !*args[2]) {
1340 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",
1341 file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345
1346 cur_arg = 2;
1347 while (*args[cur_arg]) {
1348 unsigned int low, high;
1349
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001350 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001351 char *dash = strchr(args[cur_arg], '-');
1352
1353 low = high = str2uic(args[cur_arg]);
1354 if (dash)
1355 high = str2uic(dash + 1);
1356
1357 if (high < low) {
1358 unsigned int swap = low;
1359 low = high;
1360 high = swap;
1361 }
1362
1363 if (low < 0 || high >= sizeof(long) * 8) {
1364 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1365 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
1368 }
1369
1370 while (low <= high)
1371 cpus |= 1UL << low++;
1372 }
1373 else {
1374 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1375 file, linenum, args[0], args[cur_arg]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379 cur_arg++;
1380 }
1381 for (i = 0; i < 32; i++)
1382 if (proc & (1 << i))
1383 global.cpu_map[i] = cpus;
1384#else
1385 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1386 err_code |= ERR_ALERT | ERR_FATAL;
1387 goto out;
1388#endif
1389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001391 struct cfg_kw_list *kwl;
1392 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001393 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001394
1395 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1396 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1397 if (kwl->kw[index].section != CFG_GLOBAL)
1398 continue;
1399 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001400 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001401 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001402 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001403 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001404 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001405 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001406 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 err_code |= ERR_WARN;
1408 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001409 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001410 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001411 }
1412 }
1413 }
1414
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001416 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001418
Willy Tarreau058e9072009-07-20 09:30:05 +02001419 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001420 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001421 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422}
1423
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001424void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001426 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 defproxy.mode = PR_MODE_TCP;
1428 defproxy.state = PR_STNEW;
1429 defproxy.maxconn = cfg_maxpconn;
1430 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001431
Simon Horman66183002013-02-23 10:16:43 +09001432 defproxy.defsrv.check.inter = DEF_CHKINTR;
1433 defproxy.defsrv.check.fastinter = 0;
1434 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001435 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1436 defproxy.defsrv.agent.fastinter = 0;
1437 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001438 defproxy.defsrv.check.rise = DEF_RISETIME;
1439 defproxy.defsrv.check.fall = DEF_FALLTIME;
1440 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1441 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001442 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001443 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001444 defproxy.defsrv.maxqueue = 0;
1445 defproxy.defsrv.minconn = 0;
1446 defproxy.defsrv.maxconn = 0;
1447 defproxy.defsrv.slowstart = 0;
1448 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1449 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1450 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451}
1452
Willy Tarreauade5ec42010-01-28 19:33:49 +01001453
1454static int create_cond_regex_rule(const char *file, int line,
1455 struct proxy *px, int dir, int action, int flags,
1456 const char *cmd, const char *reg, const char *repl,
1457 const char **cond_start)
1458{
1459 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001460 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001461 const char *err;
1462 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001463 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001464
1465 if (px == &defproxy) {
1466 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1467 err_code |= ERR_ALERT | ERR_FATAL;
1468 goto err;
1469 }
1470
1471 if (*reg == 0) {
1472 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto err;
1475 }
1476
1477 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1478 err_code |= ERR_WARN;
1479
Willy Tarreau5321c422010-01-28 20:35:13 +01001480 if (cond_start &&
1481 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001482 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1483 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1484 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001485 err_code |= ERR_ALERT | ERR_FATAL;
1486 goto err;
1487 }
1488 }
1489 else if (cond_start && **cond_start) {
1490 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1491 file, line, cmd, *cond_start);
1492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto err;
1494 }
1495
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001496 err_code |= warnif_cond_conflicts(cond,
1497 (dir == SMP_OPT_DIR_REQ) ?
1498 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1499 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1500 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001501
Willy Tarreauade5ec42010-01-28 19:33:49 +01001502 preg = calloc(1, sizeof(regex_t));
1503 if (!preg) {
1504 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1505 err_code = ERR_ALERT | ERR_FATAL;
1506 goto err;
1507 }
1508
1509 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1510 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1511 err_code = ERR_ALERT | ERR_FATAL;
1512 goto err;
1513 }
1514
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001515 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001516 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001517 if (repl && err) {
1518 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1519 file, line, cmd, *err);
1520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto err;
1522 }
1523
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001524 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001525 err_code |= ERR_WARN;
1526
Willy Tarreauf4068b62012-05-08 17:37:49 +02001527 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001528 return err_code;
1529 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001530 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001531 free(preg);
1532 return err_code;
1533}
1534
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001537 * Returns the error code, 0 if OK, or any combination of :
1538 * - ERR_ABORT: must abort ASAP
1539 * - ERR_FATAL: we can continue parsing but not start the service
1540 * - ERR_WARN: a warning has been emitted
1541 * - ERR_ALERT: an alert has been emitted
1542 * Only the two first ones can stop processing, the two others are just
1543 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001545int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1546{
1547 static struct peers *curpeers = NULL;
1548 struct peer *newpeer = NULL;
1549 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001550 struct bind_conf *bind_conf;
1551 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001552 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001553 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001554
1555 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001556 if (!*args[1]) {
1557 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001558 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001559 goto out;
1560 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001561
1562 err = invalid_char(args[1]);
1563 if (err) {
1564 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1565 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001566 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001567 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001568 }
1569
1570 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1571 /*
1572 * If there are two proxies with the same name only following
1573 * combinations are allowed:
1574 */
1575 if (strcmp(curpeers->id, args[1]) == 0) {
1576 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1577 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1578 err_code |= ERR_WARN;
1579 }
1580 }
1581
1582 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1583 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1584 err_code |= ERR_ALERT | ERR_ABORT;
1585 goto out;
1586 }
1587
1588 curpeers->next = peers;
1589 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001590 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001591 curpeers->conf.line = linenum;
1592 curpeers->last_change = now.tv_sec;
1593 curpeers->id = strdup(args[1]);
1594 }
1595 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001596 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001597 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001598 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001599
1600 if (!*args[2]) {
1601 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1602 file, linenum, args[0]);
1603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
1605 }
1606
1607 err = invalid_char(args[1]);
1608 if (err) {
1609 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1610 file, linenum, *err, args[1]);
1611 err_code |= ERR_ALERT | ERR_FATAL;
1612 goto out;
1613 }
1614
1615 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1616 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1617 err_code |= ERR_ALERT | ERR_ABORT;
1618 goto out;
1619 }
1620
1621 /* the peers are linked backwards first */
1622 curpeers->count++;
1623 newpeer->next = curpeers->remote;
1624 curpeers->remote = newpeer;
1625 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001626 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001627 newpeer->conf.line = linenum;
1628
1629 newpeer->last_change = now.tv_sec;
1630 newpeer->id = strdup(args[1]);
1631
Willy Tarreau902636f2013-03-10 19:44:48 +01001632 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001633 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001634 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001637 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001638
1639 proto = protocol_by_family(sk->ss_family);
1640 if (!proto || !proto->connect) {
1641 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1642 file, linenum, args[0], args[1]);
1643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
1645 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001646
1647 if (port1 != port2) {
1648 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1649 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
Willy Tarreau2aa38802013-02-20 19:20:59 +01001654 if (!port1) {
1655 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1656 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
1659 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001660
Emeric Brun32da3c42010-09-23 18:39:19 +02001661 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001662 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001663 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001664 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001665
Emeric Brun32da3c42010-09-23 18:39:19 +02001666 if (strcmp(newpeer->id, localpeer) == 0) {
1667 /* Current is local peer, it define a frontend */
1668 newpeer->local = 1;
1669
1670 if (!curpeers->peers_fe) {
1671 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1672 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1673 err_code |= ERR_ALERT | ERR_ABORT;
1674 goto out;
1675 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001676
Willy Tarreau237250c2011-07-29 01:49:03 +02001677 init_new_proxy(curpeers->peers_fe);
1678 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001679
1680 curpeers->peers_fe->last_change = now.tv_sec;
1681 curpeers->peers_fe->id = strdup(args[1]);
1682 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001683 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001684 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1685 curpeers->peers_fe->timeout.connect = 5000;
1686 curpeers->peers_fe->accept = peer_accept;
1687 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001688 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1689 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001690
1691 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1692
Willy Tarreau902636f2013-03-10 19:44:48 +01001693 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1694 if (errmsg && *errmsg) {
1695 indent_msg(&errmsg, 2);
1696 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001697 }
1698 else
1699 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1700 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001704
1705 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1706 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1707 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1708 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1709 l->accept = session_accept;
1710 l->handler = process_session;
1711 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1712 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1713 global.maxsock += l->maxconn;
1714 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001715 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001716 else {
1717 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1718 file, linenum, args[0], args[1],
1719 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1720 err_code |= ERR_FATAL;
1721 goto out;
1722 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001723 }
1724 } /* neither "peer" nor "peers" */
1725 else if (*args[0] != 0) {
1726 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
1729 }
1730
1731out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001732 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001733 return err_code;
1734}
1735
Simon Horman69d29f92013-02-23 15:14:19 +09001736static int init_check(struct check *check, int type, const char * file, int linenum)
1737{
1738 check->type = type;
1739
1740 /* Allocate buffer for requests... */
1741 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1742 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1743 return ERR_ALERT | ERR_ABORT;
1744 }
1745 check->bi->size = global.tune.chksize;
1746
1747 /* Allocate buffer for responses... */
1748 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1749 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1750 return ERR_ALERT | ERR_ABORT;
1751 }
1752 check->bo->size = global.tune.chksize;
1753
1754 /* Allocate buffer for partial results... */
1755 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1756 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1757 return ERR_ALERT | ERR_ABORT;
1758 }
1759
1760 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1761
1762 return 0;
1763}
Emeric Brun32da3c42010-09-23 18:39:19 +02001764
Willy Tarreau3842f002009-06-14 11:39:52 +02001765int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766{
1767 static struct proxy *curproxy = NULL;
1768 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001769 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001770 int rc;
1771 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001772 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001773 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001774 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001775 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001776 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Willy Tarreau977b8e42006-12-29 14:19:17 +01001778 if (!strcmp(args[0], "listen"))
1779 rc = PR_CAP_LISTEN;
1780 else if (!strcmp(args[0], "frontend"))
1781 rc = PR_CAP_FE | PR_CAP_RS;
1782 else if (!strcmp(args[0], "backend"))
1783 rc = PR_CAP_BE | PR_CAP_RS;
1784 else if (!strcmp(args[0], "ruleset"))
1785 rc = PR_CAP_RS;
1786 else
1787 rc = PR_CAP_NONE;
1788
1789 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001790 struct ebpt_node *node;
1791
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 if (!*args[1]) {
1793 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1794 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1795 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_ABORT;
1797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001799
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001800 err = invalid_char(args[1]);
1801 if (err) {
1802 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1803 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001804 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001805 }
1806
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001807 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1808 curproxy = container_of(node, struct proxy, conf.by_name);
1809
1810 if (strcmp(curproxy->id, args[1]) != 0)
1811 break;
1812
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001813 /*
1814 * If there are two proxies with the same name only following
1815 * combinations are allowed:
1816 *
1817 * listen backend frontend ruleset
1818 * listen - - - -
1819 * backend - - OK -
1820 * frontend - OK - -
1821 * ruleset - - - -
1822 */
1823
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001824 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1825 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001826 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1827 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1828 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001829 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001830 }
1831 }
1832
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1834 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001835 err_code |= ERR_ALERT | ERR_ABORT;
1836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001838
Willy Tarreau97cb7802010-01-03 20:23:58 +01001839 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 curproxy->next = proxy;
1841 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001842 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1843 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001844 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001847 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848
1849 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001850 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001851 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001852
Willy Tarreau4348fad2012-09-20 16:48:07 +02001853 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1854
Willy Tarreau902636f2013-03-10 19:44:48 +01001855 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1856 if (errmsg && *errmsg) {
1857 indent_msg(&errmsg, 2);
1858 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001859 }
1860 else
1861 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1862 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001863 err_code |= ERR_FATAL;
1864 goto out;
1865 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001866
Willy Tarreau4348fad2012-09-20 16:48:07 +02001867 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001868 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 }
1871
1872 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001873 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001874 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001875
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001878 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001879 curproxy->no_options = defproxy.no_options;
1880 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001881 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001882 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001883 curproxy->except_net = defproxy.except_net;
1884 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001885 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001886 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001888 if (defproxy.fwdfor_hdr_len) {
1889 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1890 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1891 }
1892
Willy Tarreaub86db342009-11-30 11:50:16 +01001893 if (defproxy.orgto_hdr_len) {
1894 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1895 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1896 }
1897
Mark Lamourinec2247f02012-01-04 13:02:01 -05001898 if (defproxy.server_id_hdr_len) {
1899 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1900 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1901 }
1902
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (curproxy->cap & PR_CAP_FE) {
1904 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001905 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001906 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907
1908 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001909 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1910 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911
1912 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 if (curproxy->cap & PR_CAP_BE) {
1916 curproxy->fullconn = defproxy.fullconn;
1917 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001919 if (defproxy.check_req) {
1920 curproxy->check_req = calloc(1, defproxy.check_len);
1921 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1922 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001925 if (defproxy.expect_str) {
1926 curproxy->expect_str = strdup(defproxy.expect_str);
1927 if (defproxy.expect_regex) {
1928 /* note: this regex is known to be valid */
1929 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1930 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1931 }
1932 }
1933
Willy Tarreau67402132012-05-31 20:40:20 +02001934 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 if (defproxy.cookie_name)
1936 curproxy->cookie_name = strdup(defproxy.cookie_name);
1937 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001938 if (defproxy.cookie_domain)
1939 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001940
Willy Tarreau31936852010-10-06 16:59:56 +02001941 if (defproxy.cookie_maxidle)
1942 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1943
1944 if (defproxy.cookie_maxlife)
1945 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1946
Emeric Brun647caf12009-06-30 17:57:00 +02001947 if (defproxy.rdp_cookie_name)
1948 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1949 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1950
Willy Tarreau01732802007-11-01 22:48:15 +01001951 if (defproxy.url_param_name)
1952 curproxy->url_param_name = strdup(defproxy.url_param_name);
1953 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001954
Benoitaffb4812009-03-25 13:02:10 +01001955 if (defproxy.hh_name)
1956 curproxy->hh_name = strdup(defproxy.hh_name);
1957 curproxy->hh_len = defproxy.hh_len;
1958 curproxy->hh_match_domain = defproxy.hh_match_domain;
1959
Willy Tarreauef9a3602012-12-08 22:29:20 +01001960 if (defproxy.conn_src.iface_name)
1961 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1962 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001963 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001964#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001965 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001966#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001969 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001970 if (defproxy.capture_name)
1971 curproxy->capture_name = strdup(defproxy.capture_name);
1972 curproxy->capture_namelen = defproxy.capture_namelen;
1973 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975
Willy Tarreau977b8e42006-12-29 14:19:17 +01001976 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001977 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001978 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001979 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001980 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 curproxy->uri_auth = defproxy.uri_auth;
1982 curproxy->mon_net = defproxy.mon_net;
1983 curproxy->mon_mask = defproxy.mon_mask;
1984 if (defproxy.monitor_uri)
1985 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1986 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001987 if (defproxy.defbe.name)
1988 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001989
1990 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001991 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1992 if (curproxy->conf.logformat_string &&
1993 curproxy->conf.logformat_string != default_http_log_format &&
1994 curproxy->conf.logformat_string != default_tcp_log_format &&
1995 curproxy->conf.logformat_string != clf_http_log_format)
1996 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1997
1998 if (defproxy.conf.lfs_file) {
1999 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2000 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 }
2003
2004 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002005 curproxy->timeout.connect = defproxy.timeout.connect;
2006 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002007 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002008 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002009 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002010 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002011 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002012 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002013 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002014 }
2015
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02002017
2018 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002019 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002020 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002021 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002022 LIST_INIT(&node->list);
2023 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2024 }
2025
Willy Tarreau62a61232013-04-12 18:13:46 +02002026 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2027 if (curproxy->conf.uniqueid_format_string)
2028 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2029
2030 if (defproxy.conf.uif_file) {
2031 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2032 curproxy->conf.uif_line = defproxy.conf.uif_line;
2033 }
William Lallemanda73203e2012-03-12 12:48:57 +01002034
2035 /* copy default header unique id */
2036 if (defproxy.header_unique_id)
2037 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2038
William Lallemand82fe75c2012-10-23 10:25:10 +02002039 /* default compression options */
2040 if (defproxy.comp != NULL) {
2041 curproxy->comp = calloc(1, sizeof(struct comp));
2042 curproxy->comp->algos = defproxy.comp->algos;
2043 curproxy->comp->types = defproxy.comp->types;
2044 }
2045
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002047 curproxy->conf.used_listener_id = EB_ROOT;
2048 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002049
Willy Tarreau93893792009-07-23 13:19:11 +02002050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 }
2052 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2053 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002054 /* FIXME-20070101: we should do this too at the end of the
2055 * config parsing to free all default values.
2056 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002057 free(defproxy.check_req);
2058 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002059 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002060 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002061 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002062 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002063 free(defproxy.capture_name);
2064 free(defproxy.monitor_uri);
2065 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002066 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002067 free(defproxy.fwdfor_hdr_name);
2068 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002069 free(defproxy.orgto_hdr_name);
2070 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002071 free(defproxy.server_id_hdr_name);
2072 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002073 free(defproxy.expect_str);
2074 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002075
Willy Tarreau62a61232013-04-12 18:13:46 +02002076 if (defproxy.conf.logformat_string != default_http_log_format &&
2077 defproxy.conf.logformat_string != default_tcp_log_format &&
2078 defproxy.conf.logformat_string != clf_http_log_format)
2079 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002080
Willy Tarreau62a61232013-04-12 18:13:46 +02002081 free(defproxy.conf.uniqueid_format_string);
2082 free(defproxy.conf.lfs_file);
2083 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002084
Willy Tarreaua534fea2008-08-03 12:19:50 +02002085 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002086 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 /* we cannot free uri_auth because it might already be used */
2089 init_default_instance();
2090 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002091 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2092 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 }
2096 else if (curproxy == NULL) {
2097 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_ALERT | ERR_FATAL;
2099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002101
2102 /* update the current file and line being parsed */
2103 curproxy->conf.args.file = curproxy->conf.file;
2104 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002105
2106 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002108 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002109 int cur_arg;
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 if (curproxy == &defproxy) {
2112 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002116 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118
Willy Tarreau24709282013-03-10 21:32:12 +01002119 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002120 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002121 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_FATAL;
2123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002125
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002126 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002127
2128 /* use default settings for unix sockets */
2129 bind_conf->ux.uid = global.unix_bind.ux.uid;
2130 bind_conf->ux.gid = global.unix_bind.ux.gid;
2131 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002132
2133 /* NOTE: the following line might create several listeners if there
2134 * are comma-separated IPs or port ranges. So all further processing
2135 * will have to be applied to all listeners created after last_listen.
2136 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002137 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2138 if (errmsg && *errmsg) {
2139 indent_msg(&errmsg, 2);
2140 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002141 }
2142 else
2143 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
2147 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002148
Willy Tarreau4348fad2012-09-20 16:48:07 +02002149 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2150 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002151 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002152 }
2153
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002154 cur_arg = 2;
2155 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002156 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002157 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002158 char *err;
2159
Willy Tarreau26982662012-09-12 23:17:10 +02002160 kw = bind_find_kw(args[cur_arg]);
2161 if (kw) {
2162 char *err = NULL;
2163 int code;
2164
2165 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002166 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2167 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002168 cur_arg += 1 + kw->skip ;
2169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
2171 }
2172
Willy Tarreau4348fad2012-09-20 16:48:07 +02002173 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002174 err_code |= code;
2175
2176 if (code) {
2177 if (err && *err) {
2178 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002179 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002180 }
2181 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002182 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2183 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002184 if (code & ERR_FATAL) {
2185 free(err);
2186 cur_arg += 1 + kw->skip;
2187 goto out;
2188 }
2189 }
2190 free(err);
2191 cur_arg += 1 + kw->skip;
2192 continue;
2193 }
2194
Willy Tarreau8638f482012-09-18 18:01:17 +02002195 err = NULL;
2196 if (!bind_dumped) {
2197 bind_dump_kws(&err);
2198 indent_msg(&err, 4);
2199 bind_dumped = 1;
2200 }
2201
2202 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2203 file, linenum, args[0], args[1], args[cur_arg],
2204 err ? " Registered keywords :" : "", err ? err : "");
2205 free(err);
2206
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002209 }
Willy Tarreau93893792009-07-23 13:19:11 +02002210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 }
2212 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002213 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002219 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002221
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 /* flush useless bits */
2223 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002226 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229
Willy Tarreau1c47f852006-07-09 08:22:27 +02002230 if (!*args[1]) {
2231 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2232 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002235 }
2236
Willy Tarreaua534fea2008-08-03 12:19:50 +02002237 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002238 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002239 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002240 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002241 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2242
Willy Tarreau93893792009-07-23 13:19:11 +02002243 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2246 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2247 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2248 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2249 else {
2250 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
2254 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002255 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002256 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002257
2258 if (curproxy == &defproxy) {
2259 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002263 }
2264
2265 if (!*args[1]) {
2266 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2267 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002270 }
2271
2272 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002273 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002274
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002275 if (curproxy->uuid <= 0) {
2276 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002277 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002280 }
2281
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002282 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2283 if (node) {
2284 struct proxy *target = container_of(node, struct proxy, conf.id);
2285 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2286 file, linenum, proxy_type_str(curproxy), curproxy->id,
2287 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002292 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002293 else if (!strcmp(args[0], "description")) {
2294 int i, len=0;
2295 char *d;
2296
Cyril Bonté99ed3272010-01-24 23:29:44 +01002297 if (curproxy == &defproxy) {
2298 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2299 file, linenum, args[0]);
2300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
2303
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002304 if (!*args[1]) {
2305 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2306 file, linenum, args[0]);
2307 return -1;
2308 }
2309
2310 for(i=1; *args[i]; i++)
2311 len += strlen(args[i])+1;
2312
2313 d = (char *)calloc(1, len);
2314 curproxy->desc = d;
2315
2316 d += sprintf(d, "%s", args[1]);
2317 for(i=2; *args[i]; i++)
2318 d += sprintf(d, " %s", args[i]);
2319
2320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2322 curproxy->state = PR_STSTOPPED;
2323 }
2324 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2325 curproxy->state = PR_STNEW;
2326 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002327 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2328 int cur_arg = 1;
2329 unsigned int set = 0;
2330
2331 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002332 unsigned int low, high;
2333
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002334 if (strcmp(args[cur_arg], "all") == 0) {
2335 set = 0;
2336 break;
2337 }
2338 else if (strcmp(args[cur_arg], "odd") == 0) {
2339 set |= 0x55555555;
2340 }
2341 else if (strcmp(args[cur_arg], "even") == 0) {
2342 set |= 0xAAAAAAAA;
2343 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002344 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002345 char *dash = strchr(args[cur_arg], '-');
2346
2347 low = high = str2uic(args[cur_arg]);
2348 if (dash)
2349 high = str2uic(dash + 1);
2350
2351 if (high < low) {
2352 unsigned int swap = low;
2353 low = high;
2354 high = swap;
2355 }
2356
2357 if (low < 1 || high > 32) {
2358 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002362 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002363
2364 if (high > global.nbproc) {
2365 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2366 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002368 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002369 while (low <= high)
2370 set |= 1 << (low++ - 1);
2371 }
2372 else {
2373 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002377 }
2378 cur_arg++;
2379 }
2380 curproxy->bind_proc = set;
2381 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002382 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002383 if (curproxy == &defproxy) {
2384 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002387 }
2388
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002389 err = invalid_char(args[1]);
2390 if (err) {
2391 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2392 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002394 }
2395
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002396 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002397 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2398 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002401 }
2402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2404 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002408
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 if (*(args[1]) == 0) {
2410 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002412 err_code |= ERR_ALERT | ERR_FATAL;
2413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002415
Willy Tarreau67402132012-05-31 20:40:20 +02002416 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002417 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002418 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002419 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 curproxy->cookie_name = strdup(args[1]);
2421 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002422
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 cur_arg = 2;
2424 while (*(args[cur_arg])) {
2425 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002426 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
2428 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002429 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002432 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 }
2434 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002435 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 }
2437 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002438 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002440 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002441 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002444 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002446 else if (!strcmp(args[cur_arg], "httponly")) {
2447 curproxy->ck_opts |= PR_CK_HTTPONLY;
2448 }
2449 else if (!strcmp(args[cur_arg], "secure")) {
2450 curproxy->ck_opts |= PR_CK_SECURE;
2451 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002452 else if (!strcmp(args[cur_arg], "domain")) {
2453 if (!*args[cur_arg + 1]) {
2454 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2455 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002458 }
2459
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002460 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002461 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002462 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2463 " dots nor does not start with a dot."
2464 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002465 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002466 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002467 }
2468
2469 err = invalid_domainchar(args[cur_arg + 1]);
2470 if (err) {
2471 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2472 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002475 }
2476
Willy Tarreau68a897b2009-12-03 23:28:34 +01002477 if (!curproxy->cookie_domain) {
2478 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2479 } else {
2480 /* one domain was already specified, add another one by
2481 * building the string which will be returned along with
2482 * the cookie.
2483 */
2484 char *new_ptr;
2485 int new_len = strlen(curproxy->cookie_domain) +
2486 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2487 new_ptr = malloc(new_len);
2488 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2489 free(curproxy->cookie_domain);
2490 curproxy->cookie_domain = new_ptr;
2491 }
Willy Tarreau31936852010-10-06 16:59:56 +02002492 cur_arg++;
2493 }
2494 else if (!strcmp(args[cur_arg], "maxidle")) {
2495 unsigned int maxidle;
2496 const char *res;
2497
2498 if (!*args[cur_arg + 1]) {
2499 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2500 file, linenum, args[cur_arg]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
2504
2505 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2506 if (res) {
2507 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2508 file, linenum, *res, args[cur_arg]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512 curproxy->cookie_maxidle = maxidle;
2513 cur_arg++;
2514 }
2515 else if (!strcmp(args[cur_arg], "maxlife")) {
2516 unsigned int maxlife;
2517 const char *res;
2518
2519 if (!*args[cur_arg + 1]) {
2520 Alert("parsing [%s:%d]: '%s' expects <lifetime> 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], &maxlife, 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_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002534 cur_arg++;
2535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002537 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 +02002538 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 }
2542 cur_arg++;
2543 }
Willy Tarreau67402132012-05-31 20:40:20 +02002544 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
2549
Willy Tarreau67402132012-05-31 20:40:20 +02002550 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2552 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002555
Willy Tarreau67402132012-05-31 20:40:20 +02002556 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002557 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2558 file, linenum);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002562 else if (!strcmp(args[0], "persist")) { /* persist */
2563 if (*(args[1]) == 0) {
2564 Alert("parsing [%s:%d] : missing persist method.\n",
2565 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002568 }
2569
2570 if (!strncmp(args[1], "rdp-cookie", 10)) {
2571 curproxy->options2 |= PR_O2_RDPC_PRST;
2572
Emeric Brunb982a3d2010-01-04 15:45:53 +01002573 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002574 const char *beg, *end;
2575
2576 beg = args[1] + 11;
2577 end = strchr(beg, ')');
2578
2579 if (!end || end == beg) {
2580 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2581 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002584 }
2585
2586 free(curproxy->rdp_cookie_name);
2587 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2588 curproxy->rdp_cookie_len = end-beg;
2589 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002590 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002591 free(curproxy->rdp_cookie_name);
2592 curproxy->rdp_cookie_name = strdup("msts");
2593 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2594 }
2595 else { /* syntax */
2596 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2597 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002600 }
2601 }
2602 else {
2603 Alert("parsing [%s:%d] : unknown persist method.\n",
2604 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002607 }
2608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002610 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002612 if (curproxy == &defproxy) {
2613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
Willy Tarreau977b8e42006-12-29 14:19:17 +01002618 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002620
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002622 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
2627 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002628 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629 curproxy->appsession_name = strdup(args[1]);
2630 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2631 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002632 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2633 if (err) {
2634 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2635 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002638 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002639 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002640
Willy Tarreau51041c72007-09-09 21:56:53 +02002641 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2642 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_ABORT;
2644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002646
2647 cur_arg = 6;
2648 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002649 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2650 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002651 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002652 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002653 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002654 } else if (!strcmp(args[cur_arg], "prefix")) {
2655 curproxy->options2 |= PR_O2_AS_PFX;
2656 } else if (!strcmp(args[cur_arg], "mode")) {
2657 if (!*args[cur_arg + 1]) {
2658 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2659 file, linenum, args[0], args[cur_arg]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
2664 cur_arg++;
2665 if (!strcmp(args[cur_arg], "query-string")) {
2666 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2667 curproxy->options2 |= PR_O2_AS_M_QS;
2668 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2669 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2670 curproxy->options2 |= PR_O2_AS_M_PP;
2671 } else {
2672 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002677 cur_arg++;
2678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 } /* Url App Session */
2680 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002681 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002683
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002685 if (curproxy == &defproxy) {
2686 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
2689 }
2690
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 if (*(args[4]) == 0) {
2692 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002697 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 curproxy->capture_name = strdup(args[2]);
2699 curproxy->capture_namelen = strlen(curproxy->capture_name);
2700 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 curproxy->to_log |= LW_COOKIE;
2702 }
2703 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2704 struct cap_hdr *hdr;
2705
2706 if (curproxy == &defproxy) {
2707 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 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }
2711
2712 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2713 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2714 file, linenum, args[0], args[1]);
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 }
2718
2719 hdr = calloc(sizeof(struct cap_hdr), 1);
2720 hdr->next = curproxy->req_cap;
2721 hdr->name = strdup(args[3]);
2722 hdr->namelen = strlen(args[3]);
2723 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002724 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 hdr->index = curproxy->nb_req_cap++;
2726 curproxy->req_cap = hdr;
2727 curproxy->to_log |= LW_REQHDR;
2728 }
2729 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2730 struct cap_hdr *hdr;
2731
2732 if (curproxy == &defproxy) {
2733 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 +02002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736 }
2737
2738 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2739 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2740 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 }
2744 hdr = calloc(sizeof(struct cap_hdr), 1);
2745 hdr->next = curproxy->rsp_cap;
2746 hdr->name = strdup(args[3]);
2747 hdr->namelen = strlen(args[3]);
2748 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002749 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 hdr->index = curproxy->nb_rsp_cap++;
2751 curproxy->rsp_cap = hdr;
2752 curproxy->to_log |= LW_RSPHDR;
2753 }
2754 else {
2755 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2756 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 }
2760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002764
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 if (*(args[1]) == 0) {
2766 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 }
2771 curproxy->conn_retries = atol(args[1]);
2772 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002773 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002774 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002775
2776 if (curproxy == &defproxy) {
2777 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
2780 }
2781
Willy Tarreau20b0de52012-12-24 15:45:22 +01002782 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2783 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2784 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2785 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002786 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002787 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2788 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 +01002789 file, linenum, args[0]);
2790 err_code |= ERR_WARN;
2791 }
2792
Willy Tarreauff011f22011-01-06 17:51:27 +01002793 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002794
Willy Tarreauff011f22011-01-06 17:51:27 +01002795 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002796 err_code |= ERR_ALERT | ERR_ABORT;
2797 goto out;
2798 }
2799
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002800 err_code |= warnif_cond_conflicts(rule->cond,
2801 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2802 file, linenum);
2803
Willy Tarreauff011f22011-01-06 17:51:27 +01002804 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002805 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002806 else if (!strcmp(args[0], "http-response")) { /* response access control */
2807 struct http_res_rule *rule;
2808
2809 if (curproxy == &defproxy) {
2810 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814
2815 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2816 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2817 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2818 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2819 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2820 file, linenum, args[0]);
2821 err_code |= ERR_WARN;
2822 }
2823
2824 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2825
2826 if (!rule) {
2827 err_code |= ERR_ALERT | ERR_ABORT;
2828 goto out;
2829 }
2830
2831 err_code |= warnif_cond_conflicts(rule->cond,
2832 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2833 file, linenum);
2834
2835 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2836 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002837 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2838 /* set the header name and length into the proxy structure */
2839 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2840 err_code |= ERR_WARN;
2841
2842 if (!*args[1]) {
2843 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2844 file, linenum, args[0]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
2849 /* set the desired header name */
2850 free(curproxy->server_id_hdr_name);
2851 curproxy->server_id_hdr_name = strdup(args[1]);
2852 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2853 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002854 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002855 if (curproxy == &defproxy) {
2856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002859 }
2860
Willy Tarreauef6494c2010-01-28 17:12:36 +01002861 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002862 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2863 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002866 }
2867
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002868 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2869 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2870 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002873 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002874
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002875 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002876 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002877 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002878 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002879 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002880
Cyril Bonté99ed3272010-01-24 23:29:44 +01002881 if (curproxy == &defproxy) {
2882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002887 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002888 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2889 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002892 }
2893
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002894 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002895 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002896 err_code |= warnif_cond_conflicts(rule->cond,
2897 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2898 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002899 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002900 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002901 struct switching_rule *rule;
2902
Willy Tarreaub099aca2008-10-12 17:26:37 +02002903 if (curproxy == &defproxy) {
2904 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002907 }
2908
Willy Tarreau55ea7572007-06-17 19:56:27 +02002909 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002911
2912 if (*(args[1]) == 0) {
2913 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002916 }
2917
Willy Tarreauef6494c2010-01-28 17:12:36 +01002918 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002919 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002923 }
2924
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002925 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2926 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2927 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002930 }
2931
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002932 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002933
Willy Tarreau55ea7572007-06-17 19:56:27 +02002934 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2935 rule->cond = cond;
2936 rule->be.name = strdup(args[1]);
2937 LIST_INIT(&rule->list);
2938 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2939 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002940 else if (strcmp(args[0], "use-server") == 0) {
2941 struct server_rule *rule;
2942
2943 if (curproxy == &defproxy) {
2944 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
2947 }
2948
2949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2950 err_code |= ERR_WARN;
2951
2952 if (*(args[1]) == 0) {
2953 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957
2958 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2959 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2960 file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002965 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2966 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2967 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002972 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002973
2974 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2975 rule->cond = cond;
2976 rule->srv.name = strdup(args[1]);
2977 LIST_INIT(&rule->list);
2978 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2979 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2980 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002981 else if ((!strcmp(args[0], "force-persist")) ||
2982 (!strcmp(args[0], "ignore-persist"))) {
2983 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002984
2985 if (curproxy == &defproxy) {
2986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2992 err_code |= ERR_WARN;
2993
Willy Tarreauef6494c2010-01-28 17:12:36 +01002994 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002995 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2996 file, linenum, args[0]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003001 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3002 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3003 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003008 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3009 * where force-persist is applied.
3010 */
3011 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003012
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003013 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003014 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003015 if (!strcmp(args[0], "force-persist")) {
3016 rule->type = PERSIST_TYPE_FORCE;
3017 } else {
3018 rule->type = PERSIST_TYPE_IGNORE;
3019 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003020 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003021 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003022 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003023 else if (!strcmp(args[0], "stick-table")) {
3024 int myidx = 1;
3025
Emeric Brun32da3c42010-09-23 18:39:19 +02003026 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 curproxy->table.type = (unsigned int)-1;
3028 while (*args[myidx]) {
3029 const char *err;
3030
3031 if (strcmp(args[myidx], "size") == 0) {
3032 myidx++;
3033 if (!*(args[myidx])) {
3034 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3035 file, linenum, args[myidx-1]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
3039 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3040 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3041 file, linenum, *err, args[myidx-1]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003045 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003046 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003047 else if (strcmp(args[myidx], "peers") == 0) {
3048 myidx++;
Godbach50523162013-12-11 19:48:57 +08003049 if (!*(args[myidx])) {
3050 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3051 file, linenum, args[myidx-1]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003055 curproxy->table.peers.name = strdup(args[myidx++]);
3056 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 else if (strcmp(args[myidx], "expire") == 0) {
3058 myidx++;
3059 if (!*(args[myidx])) {
3060 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3061 file, linenum, args[myidx-1]);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3066 if (err) {
3067 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3068 file, linenum, *err, args[myidx-1]);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
3071 }
3072 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003073 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003074 }
3075 else if (strcmp(args[myidx], "nopurge") == 0) {
3076 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003077 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003078 }
3079 else if (strcmp(args[myidx], "type") == 0) {
3080 myidx++;
3081 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3082 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3083 file, linenum, args[myidx]);
3084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
3086 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003087 /* myidx already points to next arg */
3088 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003089 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003090 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003091 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003092
3093 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003094 nw = args[myidx];
3095 while (*nw) {
3096 /* the "store" keyword supports a comma-separated list */
3097 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003098 sa = NULL; /* store arg */
3099 while (*nw && *nw != ',') {
3100 if (*nw == '(') {
3101 *nw = 0;
3102 sa = ++nw;
3103 while (*nw != ')') {
3104 if (!*nw) {
3105 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3106 file, linenum, args[0], cw);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110 nw++;
3111 }
3112 *nw = '\0';
3113 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003114 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003115 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003116 if (*nw)
3117 *nw++ = '\0';
3118 type = stktable_get_data_type(cw);
3119 if (type < 0) {
3120 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3121 file, linenum, args[0], cw);
3122 err_code |= ERR_ALERT | ERR_FATAL;
3123 goto out;
3124 }
Willy Tarreauac782882010-06-20 10:41:54 +02003125
3126 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3127 switch (err) {
3128 case PE_NONE: break;
3129 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003130 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003133 break;
3134
3135 case PE_ARG_MISSING:
3136 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
3140
3141 case PE_ARG_NOT_USED:
3142 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3143 file, linenum, args[0], cw);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146
3147 default:
3148 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3149 file, linenum, args[0], cw);
3150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003152 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003153 }
3154 myidx++;
3155 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003156 else {
3157 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3158 file, linenum, args[myidx]);
3159 err_code |= ERR_ALERT | ERR_FATAL;
3160 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003161 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 }
3163
3164 if (!curproxy->table.size) {
3165 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3166 file, linenum);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
3171 if (curproxy->table.type == (unsigned int)-1) {
3172 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3173 file, linenum);
3174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177 }
3178 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003179 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003180 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 int myidx = 0;
3182 const char *name = NULL;
3183 int flags;
3184
3185 if (curproxy == &defproxy) {
3186 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
3190
3191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3192 err_code |= ERR_WARN;
3193 goto out;
3194 }
3195
3196 myidx++;
3197 if ((strcmp(args[myidx], "store") == 0) ||
3198 (strcmp(args[myidx], "store-request") == 0)) {
3199 myidx++;
3200 flags = STK_IS_STORE;
3201 }
3202 else if (strcmp(args[myidx], "store-response") == 0) {
3203 myidx++;
3204 flags = STK_IS_STORE | STK_ON_RSP;
3205 }
3206 else if (strcmp(args[myidx], "match") == 0) {
3207 myidx++;
3208 flags = STK_IS_MATCH;
3209 }
3210 else if (strcmp(args[myidx], "on") == 0) {
3211 myidx++;
3212 flags = STK_IS_MATCH | STK_IS_STORE;
3213 }
3214 else {
3215 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
3220 if (*(args[myidx]) == 0) {
3221 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003226 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003227 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003228 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003229 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
3232 }
3233
3234 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003235 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3236 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3237 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003238 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003239 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003240 goto out;
3241 }
3242 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003243 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3244 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3245 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003246 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003247 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003248 goto out;
3249 }
3250 }
3251
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003252 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003253 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003254
Emeric Brunb982a3d2010-01-04 15:45:53 +01003255 if (strcmp(args[myidx], "table") == 0) {
3256 myidx++;
3257 name = args[myidx++];
3258 }
3259
Willy Tarreauef6494c2010-01-28 17:12:36 +01003260 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003261 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3262 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3263 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003265 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003266 goto out;
3267 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003268 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003269 else if (*(args[myidx])) {
3270 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3271 file, linenum, args[0], args[myidx]);
3272 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003273 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003274 goto out;
3275 }
Emeric Brun97679e72010-09-23 17:56:44 +02003276 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003277 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003278 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003279 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003280
Emeric Brunb982a3d2010-01-04 15:45:53 +01003281 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3282 rule->cond = cond;
3283 rule->expr = expr;
3284 rule->flags = flags;
3285 rule->table.name = name ? strdup(name) : NULL;
3286 LIST_INIT(&rule->list);
3287 if (flags & STK_ON_RSP)
3288 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3289 else
3290 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003295
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3297 curproxy->uri_auth = NULL; /* we must detach from the default config */
3298
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003299 if (!*args[1]) {
3300 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003301 } else if (!strcmp(args[1], "admin")) {
3302 struct stats_admin_rule *rule;
3303
3304 if (curproxy == &defproxy) {
3305 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
3309
3310 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3311 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3312 err_code |= ERR_ALERT | ERR_ABORT;
3313 goto out;
3314 }
3315
3316 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3317 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3318 file, linenum, args[0], args[1]);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003322 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3323 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3324 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003329 err_code |= warnif_cond_conflicts(cond,
3330 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3331 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003332
3333 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3334 rule->cond = cond;
3335 LIST_INIT(&rule->list);
3336 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 } else if (!strcmp(args[1], "uri")) {
3338 if (*(args[2]) == 0) {
3339 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3343 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_ABORT;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 }
3347 } else if (!strcmp(args[1], "realm")) {
3348 if (*(args[2]) == 0) {
3349 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3353 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003357 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003358 unsigned interval;
3359
3360 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3361 if (err) {
3362 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3363 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003366 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_ABORT;
3369 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003370 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003371 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003372 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003373
3374 if (curproxy == &defproxy) {
3375 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
3378 }
3379
3380 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3381 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3382 err_code |= ERR_ALERT | ERR_ABORT;
3383 goto out;
3384 }
3385
Willy Tarreauff011f22011-01-06 17:51:27 +01003386 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3387 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003388 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3389 file, linenum, args[0]);
3390 err_code |= ERR_WARN;
3391 }
3392
Willy Tarreauff011f22011-01-06 17:51:27 +01003393 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003394
Willy Tarreauff011f22011-01-06 17:51:27 +01003395 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003396 err_code |= ERR_ALERT | ERR_ABORT;
3397 goto out;
3398 }
3399
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003400 err_code |= warnif_cond_conflicts(rule->cond,
3401 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3402 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003403 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003404
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 } else if (!strcmp(args[1], "auth")) {
3406 if (*(args[2]) == 0) {
3407 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3411 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003412 err_code |= ERR_ALERT | ERR_ABORT;
3413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 }
3415 } else if (!strcmp(args[1], "scope")) {
3416 if (*(args[2]) == 0) {
3417 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3421 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_ABORT;
3423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 }
3425 } else if (!strcmp(args[1], "enable")) {
3426 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3427 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_ALERT | ERR_ABORT;
3429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003431 } else if (!strcmp(args[1], "hide-version")) {
3432 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003434 err_code |= ERR_ALERT | ERR_ABORT;
3435 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003436 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003437 } else if (!strcmp(args[1], "show-legends")) {
3438 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3440 err_code |= ERR_ALERT | ERR_ABORT;
3441 goto out;
3442 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003443 } else if (!strcmp(args[1], "show-node")) {
3444
3445 if (*args[2]) {
3446 int i;
3447 char c;
3448
3449 for (i=0; args[2][i]; i++) {
3450 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003451 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3452 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003453 break;
3454 }
3455
3456 if (!i || args[2][i]) {
3457 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3458 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3459 file, linenum, args[0], args[1]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463 }
3464
3465 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3466 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3467 err_code |= ERR_ALERT | ERR_ABORT;
3468 goto out;
3469 }
3470 } else if (!strcmp(args[1], "show-desc")) {
3471 char *desc = NULL;
3472
3473 if (*args[2]) {
3474 int i, len=0;
3475 char *d;
3476
3477 for(i=2; *args[i]; i++)
3478 len += strlen(args[i])+1;
3479
3480 desc = d = (char *)calloc(1, len);
3481
3482 d += sprintf(d, "%s", args[2]);
3483 for(i=3; *args[i]; i++)
3484 d += sprintf(d, " %s", args[i]);
3485 }
3486
3487 if (!*args[2] && !global.desc)
3488 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3489 file, linenum, args[1]);
3490 else {
3491 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3492 free(desc);
3493 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3494 err_code |= ERR_ALERT | ERR_ABORT;
3495 goto out;
3496 }
3497 free(desc);
3498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003500stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003501 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 +01003502 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003505 }
3506 }
3507 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003508 int optnum;
3509
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003510 if (*(args[1]) == '\0') {
3511 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003516
3517 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3518 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003519 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3520 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3521 file, linenum, cfg_opts[optnum].name);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
Willy Tarreau93893792009-07-23 13:19:11 +02003525 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3526 err_code |= ERR_WARN;
3527 goto out;
3528 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003529
Willy Tarreau3842f002009-06-14 11:39:52 +02003530 curproxy->no_options &= ~cfg_opts[optnum].val;
3531 curproxy->options &= ~cfg_opts[optnum].val;
3532
3533 switch (kwm) {
3534 case KWM_STD:
3535 curproxy->options |= cfg_opts[optnum].val;
3536 break;
3537 case KWM_NO:
3538 curproxy->no_options |= cfg_opts[optnum].val;
3539 break;
3540 case KWM_DEF: /* already cleared */
3541 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003542 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003543
Willy Tarreau93893792009-07-23 13:19:11 +02003544 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003545 }
3546 }
3547
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003548 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3549 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003550 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3551 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3552 file, linenum, cfg_opts2[optnum].name);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
Willy Tarreau93893792009-07-23 13:19:11 +02003556 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3557 err_code |= ERR_WARN;
3558 goto out;
3559 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003560
Willy Tarreau3842f002009-06-14 11:39:52 +02003561 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3562 curproxy->options2 &= ~cfg_opts2[optnum].val;
3563
3564 switch (kwm) {
3565 case KWM_STD:
3566 curproxy->options2 |= cfg_opts2[optnum].val;
3567 break;
3568 case KWM_NO:
3569 curproxy->no_options2 |= cfg_opts2[optnum].val;
3570 break;
3571 case KWM_DEF: /* already cleared */
3572 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003573 }
Willy Tarreau93893792009-07-23 13:19:11 +02003574 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003575 }
3576 }
3577
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003578 /* HTTP options override each other. They can be cancelled using
3579 * "no option xxx" which only switches to default mode if the mode
3580 * was this one (useful for cancelling options set in defaults
3581 * sections).
3582 */
3583 if (strcmp(args[1], "httpclose") == 0) {
3584 if (kwm == KWM_STD) {
3585 curproxy->options &= ~PR_O_HTTP_MODE;
3586 curproxy->options |= PR_O_HTTP_PCL;
3587 goto out;
3588 }
3589 else if (kwm == KWM_NO) {
3590 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3591 curproxy->options &= ~PR_O_HTTP_MODE;
3592 goto out;
3593 }
3594 }
3595 else if (strcmp(args[1], "forceclose") == 0) {
3596 if (kwm == KWM_STD) {
3597 curproxy->options &= ~PR_O_HTTP_MODE;
3598 curproxy->options |= PR_O_HTTP_FCL;
3599 goto out;
3600 }
3601 else if (kwm == KWM_NO) {
3602 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3603 curproxy->options &= ~PR_O_HTTP_MODE;
3604 goto out;
3605 }
3606 }
3607 else if (strcmp(args[1], "http-server-close") == 0) {
3608 if (kwm == KWM_STD) {
3609 curproxy->options &= ~PR_O_HTTP_MODE;
3610 curproxy->options |= PR_O_HTTP_SCL;
3611 goto out;
3612 }
3613 else if (kwm == KWM_NO) {
3614 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3615 curproxy->options &= ~PR_O_HTTP_MODE;
3616 goto out;
3617 }
3618 }
3619 else if (strcmp(args[1], "http-keep-alive") == 0) {
3620 if (kwm == KWM_STD) {
3621 curproxy->options &= ~PR_O_HTTP_MODE;
3622 curproxy->options |= PR_O_HTTP_KAL;
3623 goto out;
3624 }
3625 else if (kwm == KWM_NO) {
3626 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3627 curproxy->options &= ~PR_O_HTTP_MODE;
3628 goto out;
3629 }
3630 }
3631 else if (strcmp(args[1], "http-tunnel") == 0) {
3632 if (kwm == KWM_STD) {
3633 curproxy->options &= ~PR_O_HTTP_MODE;
3634 curproxy->options |= PR_O_HTTP_TUN;
3635 goto out;
3636 }
3637 else if (kwm == KWM_NO) {
3638 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3639 curproxy->options &= ~PR_O_HTTP_MODE;
3640 goto out;
3641 }
3642 }
3643
Willy Tarreau3842f002009-06-14 11:39:52 +02003644 if (kwm != KWM_STD) {
3645 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003646 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003649 }
3650
Emeric Brun3a058f32009-06-30 18:26:00 +02003651 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003652 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003654 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003655 if (*(args[2]) != '\0') {
3656 if (!strcmp(args[2], "clf")) {
3657 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003658 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003659 } else {
3660 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003661 err_code |= ERR_ALERT | ERR_FATAL;
3662 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003663 }
3664 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003665 if (curproxy->conf.logformat_string != default_http_log_format &&
3666 curproxy->conf.logformat_string != default_tcp_log_format &&
3667 curproxy->conf.logformat_string != clf_http_log_format)
3668 free(curproxy->conf.logformat_string);
3669 curproxy->conf.logformat_string = logformat;
3670
3671 free(curproxy->conf.lfs_file);
3672 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3673 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003674 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003675 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003677 if (curproxy->conf.logformat_string != default_http_log_format &&
3678 curproxy->conf.logformat_string != default_tcp_log_format &&
3679 curproxy->conf.logformat_string != clf_http_log_format)
3680 free(curproxy->conf.logformat_string);
3681 curproxy->conf.logformat_string = default_tcp_log_format;
3682
3683 free(curproxy->conf.lfs_file);
3684 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3685 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 else if (!strcmp(args[1], "tcpka")) {
3688 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003689 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003690 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003691
3692 if (curproxy->cap & PR_CAP_FE)
3693 curproxy->options |= PR_O_TCP_CLI_KA;
3694 if (curproxy->cap & PR_CAP_BE)
3695 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 }
3697 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003698 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
3700
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003702 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003703 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003704 curproxy->options2 &= ~PR_O2_CHK_ANY;
3705 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 if (!*args[2]) { /* no argument */
3707 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3708 curproxy->check_len = strlen(DEF_CHECK_REQ);
3709 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003710 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 curproxy->check_req = (char *)malloc(reqlen);
3712 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003713 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003715 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 if (*args[4])
3717 reqlen += strlen(args[4]);
3718 else
3719 reqlen += strlen("HTTP/1.0");
3720
3721 curproxy->check_req = (char *)malloc(reqlen);
3722 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003723 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003725 }
3726 else if (!strcmp(args[1], "ssl-hello-chk")) {
3727 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003730
Willy Tarreaua534fea2008-08-03 12:19:50 +02003731 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003732 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003733 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003734 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003735 }
Willy Tarreau23677902007-05-08 23:50:35 +02003736 else if (!strcmp(args[1], "smtpchk")) {
3737 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003738 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003739 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003740 curproxy->options2 &= ~PR_O2_CHK_ANY;
3741 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003742
3743 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3744 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3745 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3746 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3747 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3748 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3749 curproxy->check_req = (char *)malloc(reqlen);
3750 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3751 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3752 } else {
3753 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3754 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3755 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3756 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3757 }
3758 }
3759 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003760 else if (!strcmp(args[1], "pgsql-check")) {
3761 /* use PostgreSQL request to check servers' health */
3762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3763 err_code |= ERR_WARN;
3764
3765 free(curproxy->check_req);
3766 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003767 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003768 curproxy->options2 |= PR_O2_PGSQL_CHK;
3769
3770 if (*(args[2])) {
3771 int cur_arg = 2;
3772
3773 while (*(args[cur_arg])) {
3774 if (strcmp(args[cur_arg], "user") == 0) {
3775 char * packet;
3776 uint32_t packet_len;
3777 uint32_t pv;
3778
3779 /* suboption header - needs additional argument for it */
3780 if (*(args[cur_arg+1]) == 0) {
3781 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3782 file, linenum, args[0], args[1], args[cur_arg]);
3783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
3785 }
3786
3787 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3788 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3789 pv = htonl(0x30000); /* protocol version 3.0 */
3790
3791 packet = (char*) calloc(1, packet_len);
3792
3793 memcpy(packet + 4, &pv, 4);
3794
3795 /* copy "user" */
3796 memcpy(packet + 8, "user", 4);
3797
3798 /* copy username */
3799 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3800
3801 free(curproxy->check_req);
3802 curproxy->check_req = packet;
3803 curproxy->check_len = packet_len;
3804
3805 packet_len = htonl(packet_len);
3806 memcpy(packet, &packet_len, 4);
3807 cur_arg += 2;
3808 } else {
3809 /* unknown suboption - catchall */
3810 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3811 file, linenum, args[0], args[1]);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815 } /* end while loop */
3816 }
3817 }
3818
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003819 else if (!strcmp(args[1], "redis-check")) {
3820 /* use REDIS PING request to check servers' health */
3821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3822 err_code |= ERR_WARN;
3823
3824 free(curproxy->check_req);
3825 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003826 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003827 curproxy->options2 |= PR_O2_REDIS_CHK;
3828
3829 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3830 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3831 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3832 }
3833
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003834 else if (!strcmp(args[1], "mysql-check")) {
3835 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003836 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3837 err_code |= ERR_WARN;
3838
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003839 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003840 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003841 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003842 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003843
3844 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3845 * const char mysql40_client_auth_pkt[] = {
3846 * "\x0e\x00\x00" // packet length
3847 * "\x01" // packet number
3848 * "\x00\x00" // client capabilities
3849 * "\x00\x00\x01" // max packet
3850 * "haproxy\x00" // username (null terminated string)
3851 * "\x00" // filler (always 0x00)
3852 * "\x01\x00\x00" // packet length
3853 * "\x00" // packet number
3854 * "\x01" // COM_QUIT command
3855 * };
3856 */
3857
3858 if (*(args[2])) {
3859 int cur_arg = 2;
3860
3861 while (*(args[cur_arg])) {
3862 if (strcmp(args[cur_arg], "user") == 0) {
3863 char *mysqluser;
3864 int packetlen, reqlen, userlen;
3865
3866 /* suboption header - needs additional argument for it */
3867 if (*(args[cur_arg+1]) == 0) {
3868 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3869 file, linenum, args[0], args[1], args[cur_arg]);
3870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873 mysqluser = args[cur_arg + 1];
3874 userlen = strlen(mysqluser);
3875 packetlen = userlen + 7;
3876 reqlen = packetlen + 9;
3877
3878 free(curproxy->check_req);
3879 curproxy->check_req = (char *)calloc(1, reqlen);
3880 curproxy->check_len = reqlen;
3881
3882 snprintf(curproxy->check_req, 4, "%c%c%c",
3883 ((unsigned char) packetlen & 0xff),
3884 ((unsigned char) (packetlen >> 8) & 0xff),
3885 ((unsigned char) (packetlen >> 16) & 0xff));
3886
3887 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003888 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003889 curproxy->check_req[8] = 1;
3890 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3891 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3892 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3893 cur_arg += 2;
3894 } else {
3895 /* unknown suboption - catchall */
3896 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3897 file, linenum, args[0], args[1]);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901 } /* end while loop */
3902 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003903 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003904 else if (!strcmp(args[1], "ldap-check")) {
3905 /* use LDAP request to check servers' health */
3906 free(curproxy->check_req);
3907 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003908 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003909 curproxy->options2 |= PR_O2_LDAP_CHK;
3910
3911 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3912 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3913 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3914 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003915 else if (!strcmp(args[1], "tcp-check")) {
3916 /* use raw TCPCHK send/expect to check servers' health */
3917 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3918 err_code |= ERR_WARN;
3919
3920 free(curproxy->check_req);
3921 curproxy->check_req = NULL;
3922 curproxy->options2 &= ~PR_O2_CHK_ANY;
3923 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3924 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003925 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003926 int cur_arg;
3927
3928 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3929 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003930 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003931
Willy Tarreau87cf5142011-08-19 22:57:24 +02003932 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003933
3934 free(curproxy->fwdfor_hdr_name);
3935 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3936 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3937
3938 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3939 cur_arg = 2;
3940 while (*(args[cur_arg])) {
3941 if (!strcmp(args[cur_arg], "except")) {
3942 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003943 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003944 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3945 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003948 }
3949 /* flush useless bits */
3950 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003951 cur_arg += 2;
3952 } else if (!strcmp(args[cur_arg], "header")) {
3953 /* suboption header - needs additional argument for it */
3954 if (*(args[cur_arg+1]) == 0) {
3955 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3956 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003959 }
3960 free(curproxy->fwdfor_hdr_name);
3961 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3962 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3963 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003964 } else if (!strcmp(args[cur_arg], "if-none")) {
3965 curproxy->options &= ~PR_O_FF_ALWAYS;
3966 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003967 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003968 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003969 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003970 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003973 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003974 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003975 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003976 else if (!strcmp(args[1], "originalto")) {
3977 int cur_arg;
3978
3979 /* insert x-original-to field, but not for the IP address listed as an except.
3980 * set default options (ie: bitfield, header name, etc)
3981 */
3982
3983 curproxy->options |= PR_O_ORGTO;
3984
3985 free(curproxy->orgto_hdr_name);
3986 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3987 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3988
Willy Tarreau87cf5142011-08-19 22:57:24 +02003989 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003990 cur_arg = 2;
3991 while (*(args[cur_arg])) {
3992 if (!strcmp(args[cur_arg], "except")) {
3993 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003994 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 +02003995 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3996 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003999 }
4000 /* flush useless bits */
4001 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4002 cur_arg += 2;
4003 } else if (!strcmp(args[cur_arg], "header")) {
4004 /* suboption header - needs additional argument for it */
4005 if (*(args[cur_arg+1]) == 0) {
4006 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4007 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004010 }
4011 free(curproxy->orgto_hdr_name);
4012 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4013 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4014 cur_arg += 2;
4015 } else {
4016 /* unknown suboption - catchall */
4017 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4018 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004021 }
4022 } /* end while loop */
4023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 else {
4025 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028 }
Willy Tarreau93893792009-07-23 13:19:11 +02004029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004031 else if (!strcmp(args[0], "default_backend")) {
4032 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004034
4035 if (*(args[1]) == 0) {
4036 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004039 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004040 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004041 curproxy->defbe.name = strdup(args[1]);
4042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004044 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004045 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004046
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004047 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4048 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 /* enable reconnections to dispatch */
4051 curproxy->options |= PR_O_REDISP;
4052 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004053 else if (!strcmp(args[0], "http-check")) {
4054 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004056
4057 if (strcmp(args[1], "disable-on-404") == 0) {
4058 /* enable a graceful server shutdown on an HTTP 404 response */
4059 curproxy->options |= PR_O_DISABLE404;
4060 }
Willy Tarreauef781042010-01-27 11:53:01 +01004061 else if (strcmp(args[1], "send-state") == 0) {
4062 /* enable emission of the apparent state of a server in HTTP checks */
4063 curproxy->options2 |= PR_O2_CHK_SNDST;
4064 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004065 else if (strcmp(args[1], "expect") == 0) {
4066 const char *ptr_arg;
4067 int cur_arg;
4068
4069 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4070 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074
4075 cur_arg = 2;
4076 /* consider exclamation marks, sole or at the beginning of a word */
4077 while (*(ptr_arg = args[cur_arg])) {
4078 while (*ptr_arg == '!') {
4079 curproxy->options2 ^= PR_O2_EXP_INV;
4080 ptr_arg++;
4081 }
4082 if (*ptr_arg)
4083 break;
4084 cur_arg++;
4085 }
4086 /* now ptr_arg points to the beginning of a word past any possible
4087 * exclamation mark, and cur_arg is the argument which holds this word.
4088 */
4089 if (strcmp(ptr_arg, "status") == 0) {
4090 if (!*(args[cur_arg + 1])) {
4091 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4092 file, linenum, args[0], args[1], ptr_arg);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004097 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004098 curproxy->expect_str = strdup(args[cur_arg + 1]);
4099 }
4100 else if (strcmp(ptr_arg, "string") == 0) {
4101 if (!*(args[cur_arg + 1])) {
4102 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4103 file, linenum, args[0], args[1], ptr_arg);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004108 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004109 curproxy->expect_str = strdup(args[cur_arg + 1]);
4110 }
4111 else if (strcmp(ptr_arg, "rstatus") == 0) {
4112 if (!*(args[cur_arg + 1])) {
4113 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4114 file, linenum, args[0], args[1], ptr_arg);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004119 free(curproxy->expect_str);
4120 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4121 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004122 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4123 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4124 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4125 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 }
4130 else if (strcmp(ptr_arg, "rstring") == 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_RSTR;
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 {
4150 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4151 file, linenum, args[0], args[1], ptr_arg);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004156 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004157 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 +02004158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004160 }
4161 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004162 else if (!strcmp(args[0], "tcp-check")) {
4163 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4164 err_code |= ERR_WARN;
4165
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004166 if (strcmp(args[1], "connect") == 0) {
4167 const char *ptr_arg;
4168 int cur_arg;
4169 struct tcpcheck_rule *tcpcheck;
4170 struct list *l;
4171
4172 /* check if first rule is also a 'connect' action */
4173 l = (struct list *)&curproxy->tcpcheck_rules;
4174 if (l->p != l->n) {
4175 tcpcheck = (struct tcpcheck_rule *)l->n;
4176 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4177 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4178 file, linenum);
4179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
4181 }
4182 }
4183
4184 cur_arg = 2;
4185 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4186 tcpcheck->action = TCPCHK_ACT_CONNECT;
4187
4188 /* parsing each parameters to fill up the rule */
4189 while (*(ptr_arg = args[cur_arg])) {
4190 /* tcp port */
4191 if (strcmp(args[cur_arg], "port") == 0) {
4192 if ( (atol(args[cur_arg + 1]) > 65535) ||
4193 (atol(args[cur_arg + 1]) < 1) ){
4194 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4195 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
4198 }
4199 tcpcheck->port = atol(args[cur_arg + 1]);
4200 cur_arg += 2;
4201 }
4202 /* send proxy protocol */
4203 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4204 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4205 cur_arg++;
4206 }
4207#ifdef USE_OPENSSL
4208 else if (strcmp(args[cur_arg], "ssl") == 0) {
4209 curproxy->options |= PR_O_TCPCHK_SSL;
4210 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4211 cur_arg++;
4212 }
4213#endif /* USE_OPENSSL */
4214 else {
4215#ifdef USE_OPENSSL
4216 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4217#else /* USE_OPENSSL */
4218 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4219#endif /* USE_OPENSSL */
4220 file, linenum, args[0], args[1], args[cur_arg]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
4224
4225 }
4226
4227 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4228 }
4229 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004230 if (! *(args[2]) ) {
4231 /* SEND string expected */
4232 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4233 file, linenum, args[0], args[1], args[2]);
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
4236 } else {
4237 struct tcpcheck_rule *tcpcheck;
4238
4239 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4240
4241 tcpcheck->action = TCPCHK_ACT_SEND;
4242 tcpcheck->string_len = strlen(args[2]);
4243 tcpcheck->string = strdup(args[2]);
4244 tcpcheck->expect_regex = NULL;
4245
4246 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4247 }
4248 }
4249 else if (strcmp(args[1], "send-binary") == 0) {
4250 if (! *(args[2]) ) {
4251 /* SEND binary string expected */
4252 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4253 file, linenum, args[0], args[1], args[2]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 } else {
4257 struct tcpcheck_rule *tcpcheck;
4258 char *err = NULL;
4259
4260 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4261
4262 tcpcheck->action = TCPCHK_ACT_SEND;
4263 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4264 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4265 file, linenum, args[0], args[1], args[2], err);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269 tcpcheck->expect_regex = NULL;
4270
4271 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4272 }
4273 }
4274 else if (strcmp(args[1], "expect") == 0) {
4275 const char *ptr_arg;
4276 int cur_arg;
4277 int inverse = 0;
4278
4279 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4280 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
4283 }
4284
4285 cur_arg = 2;
4286 /* consider exclamation marks, sole or at the beginning of a word */
4287 while (*(ptr_arg = args[cur_arg])) {
4288 while (*ptr_arg == '!') {
4289 inverse = !inverse;
4290 ptr_arg++;
4291 }
4292 if (*ptr_arg)
4293 break;
4294 cur_arg++;
4295 }
4296 /* now ptr_arg points to the beginning of a word past any possible
4297 * exclamation mark, and cur_arg is the argument which holds this word.
4298 */
4299 if (strcmp(ptr_arg, "binary") == 0) {
4300 if (!*(args[cur_arg + 1])) {
4301 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4302 file, linenum, args[0], args[1], ptr_arg);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306 struct tcpcheck_rule *tcpcheck;
4307 char *err = NULL;
4308
4309 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4310
4311 tcpcheck->action = TCPCHK_ACT_EXPECT;
4312 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4314 file, linenum, args[0], args[1], args[2], err);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 tcpcheck->expect_regex = NULL;
4319 tcpcheck->inverse = inverse;
4320
4321 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4322 }
4323 else if (strcmp(ptr_arg, "string") == 0) {
4324 if (!*(args[cur_arg + 1])) {
4325 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4326 file, linenum, args[0], args[1], ptr_arg);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 struct tcpcheck_rule *tcpcheck;
4331
4332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4333
4334 tcpcheck->action = TCPCHK_ACT_EXPECT;
4335 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4336 tcpcheck->string = strdup(args[cur_arg + 1]);
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, "rstring") == 0) {
4343 if (!*(args[cur_arg + 1])) {
4344 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> 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 = 0;
4355 tcpcheck->string = NULL;
4356 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4357 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4358 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4359 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
4362 }
4363 tcpcheck->inverse = inverse;
4364
4365 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4366 }
4367 else {
4368 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4369 file, linenum, args[0], args[1], ptr_arg);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373 }
4374 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004375 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
4379 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004380 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004381 if (curproxy == &defproxy) {
4382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004385 }
4386
Willy Tarreaub80c2302007-11-30 20:51:32 +01004387 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004389
4390 if (strcmp(args[1], "fail") == 0) {
4391 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004392 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004393 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4394 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004397 }
4398
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004399 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4400 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4401 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004404 }
4405 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4406 }
4407 else {
4408 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004411 }
4412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004413#ifdef TPROXY
4414 else if (!strcmp(args[0], "transparent")) {
4415 /* enable transparent proxy connections */
4416 curproxy->options |= PR_O_TRANSP;
4417 }
4418#endif
4419 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004420 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004422
Willy Tarreaubaaee002006-06-26 02:48:02 +02004423 if (*(args[1]) == 0) {
4424 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 }
4428 curproxy->maxconn = atol(args[1]);
4429 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004430 else if (!strcmp(args[0], "backlog")) { /* backlog */
4431 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004433
4434 if (*(args[1]) == 0) {
4435 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004438 }
4439 curproxy->backlog = atol(args[1]);
4440 }
Willy Tarreau86034312006-12-29 00:10:33 +01004441 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004442 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004444
Willy Tarreau86034312006-12-29 00:10:33 +01004445 if (*(args[1]) == 0) {
4446 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004449 }
4450 curproxy->fullconn = atol(args[1]);
4451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4453 if (*(args[1]) == 0) {
4454 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004458 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4459 if (err) {
4460 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4461 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004464 }
4465 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 }
4467 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004468 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004469 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004470 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004471
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 if (curproxy == &defproxy) {
4473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 Tarreau977b8e42006-12-29 14:19:17 +01004477 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004479
Willy Tarreau902636f2013-03-10 19:44:48 +01004480 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004481 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004482 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004484 goto out;
4485 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004486
4487 proto = protocol_by_family(sk->ss_family);
4488 if (!proto || !proto->connect) {
4489 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4490 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494
4495 if (port1 != port2) {
4496 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4497 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004501
4502 if (!port1) {
4503 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4504 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004505 err_code |= ERR_ALERT | ERR_FATAL;
4506 goto out;
4507 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004508
Willy Tarreaud5191e72010-02-09 20:50:45 +01004509 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004510 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
4512 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004515
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004516 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4517 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004522 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004523 /**
4524 * The syntax for hash-type config element is
4525 * hash-type {map-based|consistent} [[<algo>] avalanche]
4526 *
4527 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4528 */
4529 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004530
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4532 err_code |= ERR_WARN;
4533
4534 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004535 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4536 }
4537 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004538 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4539 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004540 else if (strcmp(args[1], "avalanche") == 0) {
4541 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]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004544 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004545 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004546 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549 }
Bhaskar98634f02013-10-29 23:30:51 -04004550
4551 /* set the hash function to use */
4552 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004553 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004554 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004555
4556 /* if consistent with no argument, then avalanche modifier is also applied */
4557 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4558 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004559 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004560 /* set the hash function */
4561 if (!strcmp(args[2], "sdbm")) {
4562 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4563 }
4564 else if (!strcmp(args[2], "djb2")) {
4565 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004566 } else if (!strcmp(args[2], "wt6")) {
4567 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004568 }
4569 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004570 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 -05004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
4573 }
4574
4575 /* set the hash modifier */
4576 if (!strcmp(args[3], "avalanche")) {
4577 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4578 }
4579 else if (*args[3]) {
4580 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
4583 }
Bhaskar98634f02013-10-29 23:30:51 -04004584 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004585 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004586 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004588 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004589 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004591 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004596 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598
4599 if (!*args[2]) {
4600 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4601 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004605
4606 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004607 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004608 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4609 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004612 }
4613
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004614 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004615 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004616 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004617 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004618
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004619 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4620 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4621 err_code |= ERR_ALERT | ERR_ABORT;
4622 goto out;
4623 }
4624
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 /* the servers are linked backwards first */
4626 newsrv->next = curproxy->srv;
4627 curproxy->srv = newsrv;
4628 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004629 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004630 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004632 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004633 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004634 LIST_INIT(&newsrv->pendconns);
4635 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004636 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004637 newsrv->state = SRV_RUNNING; /* early server setup */
4638 newsrv->last_change = now.tv_sec;
4639 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004641 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004642 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004643 * - IP: => port=+0, relative
4644 * - IP:N => port=N, absolute
4645 * - IP:+N => port=+N, relative
4646 * - IP:-N => port=-N, relative
4647 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004648 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004649 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004650 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004651 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004652 goto out;
4653 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004654
4655 proto = protocol_by_family(sk->ss_family);
4656 if (!proto || !proto->connect) {
4657 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4658 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
4661 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004662
4663 if (!port1 || !port2) {
4664 /* no port specified, +offset, -offset */
4665 newsrv->state |= SRV_MAPPORTS;
4666 }
4667 else if (port1 != port2) {
4668 /* port range */
4669 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4670 file, linenum, args[0], args[1], args[2]);
4671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
4673 }
4674 else {
4675 /* used by checks */
4676 realport = port1;
4677 }
4678
Willy Tarreaud5191e72010-02-09 20:50:45 +01004679 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004680 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4681 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004682
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004683 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004684 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4685 file, linenum, newsrv->addr.ss_family, args[2]);
4686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
4688 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004689
Simon Hormand60d6912013-11-25 10:46:36 +09004690 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004691 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004692 newsrv->check.inter = curproxy->defsrv.check.inter;
4693 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4694 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004695 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4696 newsrv->agent.port = curproxy->defsrv.agent.port;
4697 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4698 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4699 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004700 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4701 newsrv->minconn = curproxy->defsrv.minconn;
4702 newsrv->maxconn = curproxy->defsrv.maxconn;
4703 newsrv->slowstart = curproxy->defsrv.slowstart;
4704 newsrv->onerror = curproxy->defsrv.onerror;
Willy Tarreauabd03df2014-02-18 10:36:15 +01004705 newsrv->onmarkeddown = curproxy->defsrv.onmarkeddown;
4706 newsrv->onmarkedup = curproxy->defsrv.onmarkedup;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004707 newsrv->consecutive_errors_limit
4708 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004709#ifdef OPENSSL
4710 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4711#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004712 newsrv->uweight = newsrv->iweight
4713 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714
Simon Horman69d29f92013-02-23 15:14:19 +09004715 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004716 newsrv->check.rise = curproxy->defsrv.check.rise;
4717 newsrv->check.fall = curproxy->defsrv.check.fall;
4718 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004719 newsrv->check.server = newsrv;
4720
Simon Hormand60d6912013-11-25 10:46:36 +09004721 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004722 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4723 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4724 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004725 newsrv->agent.server = newsrv;
4726
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004727 cur_arg = 3;
4728 } else {
4729 newsrv = &curproxy->defsrv;
4730 cur_arg = 1;
4731 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004732
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004734 if (!strcmp(args[cur_arg], "agent-check")) {
4735 global.maxsock++;
4736 do_agent = 1;
4737 cur_arg += 1;
4738 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4739 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4740 if (err) {
4741 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4742 file, linenum, *err, newsrv->id);
4743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
4745 }
4746 if (val <= 0) {
4747 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4748 file, linenum, val, args[cur_arg], newsrv->id);
4749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
4751 }
4752 newsrv->agent.inter = val;
4753 cur_arg += 2;
4754 }
4755 else if (!strcmp(args[cur_arg], "agent-port")) {
4756 global.maxsock++;
4757 newsrv->agent.port = atol(args[cur_arg + 1]);
4758 cur_arg += 2;
4759 }
4760 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 newsrv->cookie = strdup(args[cur_arg + 1]);
4762 newsrv->cklen = strlen(args[cur_arg + 1]);
4763 cur_arg += 2;
4764 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004765 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004766 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4767 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4768 cur_arg += 2;
4769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004771 if (!*args[cur_arg + 1]) {
4772 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4773 file, linenum, args[cur_arg]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
4777
Simon Horman58c32972013-11-25 10:46:38 +09004778 newsrv->check.rise = atol(args[cur_arg + 1]);
4779 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004780 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4781 file, linenum, args[cur_arg]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
4785
Simon Horman125d0992013-02-24 17:23:38 +09004786 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004787 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004788 cur_arg += 2;
4789 }
4790 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004791 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004792
4793 if (!*args[cur_arg + 1]) {
4794 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4795 file, linenum, args[cur_arg]);
4796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
4798 }
4799
Simon Horman58c32972013-11-25 10:46:38 +09004800 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004801 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4802 file, linenum, args[cur_arg]);
4803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
4805 }
4806
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 cur_arg += 2;
4808 }
4809 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004810 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4811 if (err) {
4812 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4813 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004816 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004817 if (val <= 0) {
4818 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4819 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004822 }
Simon Horman66183002013-02-23 10:16:43 +09004823 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 cur_arg += 2;
4825 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004826 else if (!strcmp(args[cur_arg], "fastinter")) {
4827 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4828 if (err) {
4829 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4830 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004833 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004834 if (val <= 0) {
4835 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4836 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004839 }
Simon Horman66183002013-02-23 10:16:43 +09004840 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004841 cur_arg += 2;
4842 }
4843 else if (!strcmp(args[cur_arg], "downinter")) {
4844 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4845 if (err) {
4846 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4847 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004850 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004851 if (val <= 0) {
4852 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4853 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004856 }
Simon Horman66183002013-02-23 10:16:43 +09004857 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004858 cur_arg += 2;
4859 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004860 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004861 struct sockaddr_storage *sk;
4862 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004863 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004864
Willy Tarreau902636f2013-03-10 19:44:48 +01004865 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004866 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004867 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004868 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004869 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004870 goto out;
4871 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004872
4873 proto = protocol_by_family(sk->ss_family);
4874 if (!proto || !proto->connect) {
4875 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004876 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004880
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004881 if (port1 != port2) {
4882 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4883 file, linenum, args[cur_arg], args[cur_arg + 1]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887
Simon Horman66183002013-02-23 10:16:43 +09004888 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004889 cur_arg += 2;
4890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004892 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 cur_arg += 2;
4894 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004895 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 newsrv->state |= SRV_BACKUP;
4897 cur_arg ++;
4898 }
Simon Hormanfa461682011-06-25 09:39:49 +09004899 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4900 newsrv->state |= SRV_NON_STICK;
4901 cur_arg ++;
4902 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004903 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4904 newsrv->state |= SRV_SEND_PROXY;
4905 cur_arg ++;
4906 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004907 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4908 newsrv->check.send_proxy = 1;
4909 cur_arg ++;
4910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 else if (!strcmp(args[cur_arg], "weight")) {
4912 int w;
4913 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004914 if (w < 0 || w > SRV_UWGHT_MAX) {
4915 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4916 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004920 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 cur_arg += 2;
4922 }
4923 else if (!strcmp(args[cur_arg], "minconn")) {
4924 newsrv->minconn = atol(args[cur_arg + 1]);
4925 cur_arg += 2;
4926 }
4927 else if (!strcmp(args[cur_arg], "maxconn")) {
4928 newsrv->maxconn = atol(args[cur_arg + 1]);
4929 cur_arg += 2;
4930 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004931 else if (!strcmp(args[cur_arg], "maxqueue")) {
4932 newsrv->maxqueue = atol(args[cur_arg + 1]);
4933 cur_arg += 2;
4934 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004935 else if (!strcmp(args[cur_arg], "slowstart")) {
4936 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004937 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004938 if (err) {
4939 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4940 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004943 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004944 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004945 cur_arg += 2;
4946 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004947 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004948
4949 if (!*args[cur_arg + 1]) {
4950 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4951 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004954 }
4955
4956 newsrv->trackit = strdup(args[cur_arg + 1]);
4957
4958 cur_arg += 2;
4959 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004960 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 global.maxsock++;
4962 do_check = 1;
4963 cur_arg += 1;
4964 }
Willy Tarreau96839092010-03-29 10:02:24 +02004965 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4966 newsrv->state |= SRV_MAINTAIN;
4967 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004968 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004969 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004970 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004971 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004972 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004973 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004974 if (!strcmp(args[cur_arg + 1], "none"))
4975 newsrv->observe = HANA_OBS_NONE;
4976 else if (!strcmp(args[cur_arg + 1], "layer4"))
4977 newsrv->observe = HANA_OBS_LAYER4;
4978 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4979 if (curproxy->mode != PR_MODE_HTTP) {
4980 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4981 file, linenum, args[cur_arg + 1]);
4982 err_code |= ERR_ALERT;
4983 }
4984 newsrv->observe = HANA_OBS_LAYER7;
4985 }
4986 else {
4987 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004988 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004989 file, linenum, args[cur_arg], args[cur_arg + 1]);
4990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
4992 }
4993
4994 cur_arg += 2;
4995 }
4996 else if (!strcmp(args[cur_arg], "on-error")) {
4997 if (!strcmp(args[cur_arg + 1], "fastinter"))
4998 newsrv->onerror = HANA_ONERR_FASTINTER;
4999 else if (!strcmp(args[cur_arg + 1], "fail-check"))
5000 newsrv->onerror = HANA_ONERR_FAILCHK;
5001 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
5002 newsrv->onerror = HANA_ONERR_SUDDTH;
5003 else if (!strcmp(args[cur_arg + 1], "mark-down"))
5004 newsrv->onerror = HANA_ONERR_MARKDWN;
5005 else {
5006 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02005007 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005008 file, linenum, args[cur_arg], args[cur_arg + 1]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012
5013 cur_arg += 2;
5014 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09005015 else if (!strcmp(args[cur_arg], "on-marked-down")) {
5016 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
5017 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
5018 else {
5019 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
5020 file, linenum, args[cur_arg], args[cur_arg + 1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
5025 cur_arg += 2;
5026 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005027 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5028 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5029 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5030 else {
5031 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5032 file, linenum, args[cur_arg], args[cur_arg + 1]);
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
5036
5037 cur_arg += 2;
5038 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005039 else if (!strcmp(args[cur_arg], "error-limit")) {
5040 if (!*args[cur_arg + 1]) {
5041 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5042 file, linenum, args[cur_arg]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046
5047 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5048
5049 if (newsrv->consecutive_errors_limit <= 0) {
5050 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5051 file, linenum, args[cur_arg]);
5052 err_code |= ERR_ALERT | ERR_FATAL;
5053 goto out;
5054 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005055 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005056 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005057 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005058 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005059 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005060 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005061
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005063 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5064 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005068
Willy Tarreauef9a3602012-12-08 22:29:20 +01005069 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005070 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005071 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005072 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005073 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005075 goto out;
5076 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005077
5078 proto = protocol_by_family(sk->ss_family);
5079 if (!proto || !proto->connect) {
5080 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5081 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005085
Willy Tarreauef9a3602012-12-08 22:29:20 +01005086 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005087
5088 if (port_low != port_high) {
5089 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005090
5091 if (!port_low || !port_high) {
5092 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5093 file, linenum, args[cur_arg], args[cur_arg + 1]);
5094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
5096 }
5097
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005098 if (port_low <= 0 || port_low > 65535 ||
5099 port_high <= 0 || port_high > 65535 ||
5100 port_low > port_high) {
5101 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5102 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005105 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005106 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5107 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5108 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005109 }
5110
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005112 while (*(args[cur_arg])) {
5113 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005114#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5115#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005116 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005117 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5118 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005121 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005122#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005123 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005124 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005125 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005128 }
5129 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005130 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5131 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005132 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005133 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5134 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005135 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5136 char *name, *end;
5137
5138 name = args[cur_arg+1] + 7;
5139 while (isspace(*name))
5140 name++;
5141
5142 end = name;
5143 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5144 end++;
5145
Willy Tarreauef9a3602012-12-08 22:29:20 +01005146 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5147 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5148 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5149 newsrv->conn_src.bind_hdr_len = end - name;
5150 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5151 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5152 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005153
5154 /* now look for an occurrence number */
5155 while (isspace(*end))
5156 end++;
5157 if (*end == ',') {
5158 end++;
5159 name = end;
5160 if (*end == '-')
5161 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005162 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005163 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005164 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005165 }
5166
Willy Tarreauef9a3602012-12-08 22:29:20 +01005167 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005168 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5169 " occurrences values smaller than %d.\n",
5170 file, linenum, MAX_HDR_HISTORY);
5171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005174 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005175 struct sockaddr_storage *sk;
5176 int port1, port2;
5177
Willy Tarreau902636f2013-03-10 19:44:48 +01005178 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005179 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005180 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005181 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005182 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005183 goto out;
5184 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005185
5186 proto = protocol_by_family(sk->ss_family);
5187 if (!proto || !proto->connect) {
5188 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5189 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005193
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005194 if (port1 != port2) {
5195 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5196 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005200 newsrv->conn_src.tproxy_addr = *sk;
5201 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005202 }
5203 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005204#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005205 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005206#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005207 cur_arg += 2;
5208 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005209#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005210 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005211 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005214#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005215 } /* "usesrc" */
5216
5217 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5218#ifdef SO_BINDTODEVICE
5219 if (!*args[cur_arg + 1]) {
5220 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5221 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005224 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005225 free(newsrv->conn_src.iface_name);
5226 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5227 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005228 global.last_checks |= LSTCHK_NETADM;
5229#else
5230 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5231 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005234#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005235 cur_arg += 2;
5236 continue;
5237 }
5238 /* this keyword in not an option of "source" */
5239 break;
5240 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005242 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005243 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5244 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005249 static int srv_dumped;
5250 struct srv_kw *kw;
5251 char *err;
5252
5253 kw = srv_find_kw(args[cur_arg]);
5254 if (kw) {
5255 char *err = NULL;
5256 int code;
5257
5258 if (!kw->parse) {
5259 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5260 file, linenum, args[0], args[1], args[cur_arg]);
5261 cur_arg += 1 + kw->skip ;
5262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265
5266 if (defsrv && !kw->default_ok) {
5267 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5268 file, linenum, args[0], args[1], args[cur_arg]);
5269 cur_arg += 1 + kw->skip ;
5270 err_code |= ERR_ALERT;
5271 continue;
5272 }
5273
5274 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5275 err_code |= code;
5276
5277 if (code) {
5278 if (err && *err) {
5279 indent_msg(&err, 2);
5280 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5281 }
5282 else
5283 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5284 file, linenum, args[0], args[1], args[cur_arg]);
5285 if (code & ERR_FATAL) {
5286 free(err);
5287 cur_arg += 1 + kw->skip;
5288 goto out;
5289 }
5290 }
5291 free(err);
5292 cur_arg += 1 + kw->skip;
5293 continue;
5294 }
5295
5296 err = NULL;
5297 if (!srv_dumped) {
5298 srv_dump_kws(&err);
5299 indent_msg(&err, 4);
5300 srv_dumped = 1;
5301 }
5302
5303 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5304 file, linenum, args[0], args[1], args[cur_arg],
5305 err ? " Registered keywords :" : "", err ? err : "");
5306 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005307
Willy Tarreau93893792009-07-23 13:19:11 +02005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 }
5311 }
5312
Simon Horman8c3d0be2013-11-25 10:46:40 +09005313 /* Set initial drain state using now-configured weight */
5314 set_server_drain_state(newsrv);
5315
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005317 int ret;
5318
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005319 if (newsrv->trackit) {
5320 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5321 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005324 }
5325
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005326 /* If neither a port nor an addr was specified and no check transport
5327 * layer is forced, then the transport layer used by the checks is the
5328 * same as for the production traffic. Otherwise we use raw_sock by
5329 * default, unless one is specified.
5330 */
Simon Horman66183002013-02-23 10:16:43 +09005331 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005332#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005333 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005334#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005335 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5336 }
Simon Horman66183002013-02-23 10:16:43 +09005337 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005338 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005339 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005340
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005341 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005342 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005343
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005344 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005345 /* not yet valid, because no port was set on
5346 * the server either. We'll check if we have
5347 * a known port on the first listener.
5348 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005349 struct listener *l;
5350
5351 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005352 newsrv->check.port = get_host_port(&l->addr);
5353 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005354 break;
5355 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005356 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005357 /*
5358 * We need at least a service port, a check port or the first tcp-check rule must
5359 * be a 'connect' one
5360 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005361 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005362 struct tcpcheck_rule *n = NULL, *r = NULL;
5363 struct list *l;
5364
5365 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5366 if (!r) {
5367 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5368 file, linenum, newsrv->id);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5373 Alert("parsing [%s:%d] : server %s has neither service port nor check port nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
5374 file, linenum, newsrv->id);
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378 else {
5379 /* scan the tcp-check ruleset to ensure a port has been configured */
5380 l = &newsrv->proxy->tcpcheck_rules;
5381 list_for_each_entry(n, l, list) {
5382 r = (struct tcpcheck_rule *)n->list.p;
5383 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5384 Alert("parsing [%s:%d] : server %s has neither service port nor check port, and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
5385 file, linenum, newsrv->id);
5386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
5388 }
5389 }
5390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005392
Willy Tarreau2f075e92013-12-03 11:11:34 +01005393 /* note: check type will be set during the config review phase */
5394 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005395 if (ret) {
5396 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005397 goto out;
5398 }
5399
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005400 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 }
5402
Simon Hormand60d6912013-11-25 10:46:36 +09005403 if (do_agent) {
5404 int ret;
5405
5406 if (!newsrv->agent.port) {
5407 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5408 file, linenum, newsrv->id);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412
5413 if (!newsrv->agent.inter)
5414 newsrv->agent.inter = newsrv->check.inter;
5415
5416 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5417 if (ret) {
5418 err_code |= ret;
5419 goto out;
5420 }
5421
Willy Tarreau33434322013-12-11 21:15:19 +01005422 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005423 }
5424
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005425 if (!defsrv) {
5426 if (newsrv->state & SRV_BACKUP)
5427 curproxy->srv_bck++;
5428 else
5429 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005430
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005431 newsrv->prev_state = newsrv->state;
5432 }
William Lallemanda73203e2012-03-12 12:48:57 +01005433 }
5434
5435 else if (strcmp(args[0], "unique-id-format") == 0) {
5436 if (!*(args[1])) {
5437 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
William Lallemand3203ff42012-11-11 17:30:56 +01005441 if (*(args[2])) {
5442 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005446 free(curproxy->conf.uniqueid_format_string);
5447 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005448
Willy Tarreau62a61232013-04-12 18:13:46 +02005449 free(curproxy->conf.uif_file);
5450 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5451 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005452 }
William Lallemanda73203e2012-03-12 12:48:57 +01005453
5454 else if (strcmp(args[0], "unique-id-header") == 0) {
5455 if (!*(args[1])) {
5456 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
5460 free(curproxy->header_unique_id);
5461 curproxy->header_unique_id = strdup(args[1]);
5462 }
5463
William Lallemand723b73a2012-02-08 16:37:49 +01005464 else if (strcmp(args[0], "log-format") == 0) {
5465 if (!*(args[1])) {
5466 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
William Lallemand3203ff42012-11-11 17:30:56 +01005470 if (*(args[2])) {
5471 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005475
Willy Tarreau62a61232013-04-12 18:13:46 +02005476 if (curproxy->conf.logformat_string != default_http_log_format &&
5477 curproxy->conf.logformat_string != default_tcp_log_format &&
5478 curproxy->conf.logformat_string != clf_http_log_format)
5479 free(curproxy->conf.logformat_string);
5480 curproxy->conf.logformat_string = strdup(args[1]);
5481
5482 free(curproxy->conf.lfs_file);
5483 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5484 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005485
5486 /* get a chance to improve log-format error reporting by
5487 * reporting the correct line-number when possible.
5488 */
5489 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5490 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5491 file, linenum, curproxy->id);
5492 err_code |= ERR_WARN;
5493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
William Lallemand723b73a2012-02-08 16:37:49 +01005495
William Lallemand0f99e342011-10-12 17:50:54 +02005496 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5497 /* delete previous herited or defined syslog servers */
5498 struct logsrv *back;
5499
5500 if (*(args[1]) != 0) {
5501 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
5505
William Lallemand723b73a2012-02-08 16:37:49 +01005506 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5507 LIST_DEL(&tmplogsrv->list);
5508 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005509 }
5510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005512 struct logsrv *logsrv;
5513
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005515 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005516 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005517 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005518 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005519 LIST_INIT(&node->list);
5520 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
5523 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005524 struct sockaddr_storage *sk;
5525 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005526
5527 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528
William Lallemand0f99e342011-10-12 17:50:54 +02005529 logsrv->facility = get_log_facility(args[2]);
5530 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 }
5536
William Lallemand0f99e342011-10-12 17:50:54 +02005537 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005539 logsrv->level = get_log_level(args[3]);
5540 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005542 err_code |= ERR_ALERT | ERR_FATAL;
5543 goto out;
5544
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
5546 }
5547
William Lallemand0f99e342011-10-12 17:50:54 +02005548 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005549 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005550 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005551 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005552 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005553 err_code |= ERR_ALERT | ERR_FATAL;
5554 goto out;
5555
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005556 }
5557 }
5558
Willy Tarreau902636f2013-03-10 19:44:48 +01005559 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005560 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005561 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005562 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005563 goto out;
5564 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005565
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005566 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005567
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005568 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005569 if (port1 != port2) {
5570 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5571 file, linenum, args[0], args[1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005576 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005577 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 }
William Lallemand0f99e342011-10-12 17:50:54 +02005579
5580 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 }
5582 else {
5583 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5584 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 }
5588 }
5589 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005590 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005591 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005592 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005593 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005594
Willy Tarreau977b8e42006-12-29 14:19:17 +01005595 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005597
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005599 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5600 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005604
5605 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005606 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5607 free(curproxy->conn_src.iface_name);
5608 curproxy->conn_src.iface_name = NULL;
5609 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005610
Willy Tarreau902636f2013-03-10 19:44:48 +01005611 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005612 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005613 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005614 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005615 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005616 goto out;
5617 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005618
5619 proto = protocol_by_family(sk->ss_family);
5620 if (!proto || !proto->connect) {
5621 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005622 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005623 err_code |= ERR_ALERT | ERR_FATAL;
5624 goto out;
5625 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005626
5627 if (port1 != port2) {
5628 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5629 file, linenum, args[0], args[1]);
5630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632 }
5633
Willy Tarreauef9a3602012-12-08 22:29:20 +01005634 curproxy->conn_src.source_addr = *sk;
5635 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005636
5637 cur_arg = 2;
5638 while (*(args[cur_arg])) {
5639 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005640#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5641#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005642 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005643 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5644 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005647 }
5648#endif
5649 if (!*args[cur_arg + 1]) {
5650 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5651 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005654 }
5655
5656 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005657 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5658 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005659 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005660 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5661 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005662 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5663 char *name, *end;
5664
5665 name = args[cur_arg+1] + 7;
5666 while (isspace(*name))
5667 name++;
5668
5669 end = name;
5670 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5671 end++;
5672
Willy Tarreauef9a3602012-12-08 22:29:20 +01005673 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5674 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5675 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5676 curproxy->conn_src.bind_hdr_len = end - name;
5677 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5678 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5679 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005680
5681 /* now look for an occurrence number */
5682 while (isspace(*end))
5683 end++;
5684 if (*end == ',') {
5685 end++;
5686 name = end;
5687 if (*end == '-')
5688 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005689 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005690 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005691 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005692 }
5693
Willy Tarreauef9a3602012-12-08 22:29:20 +01005694 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005695 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5696 " occurrences values smaller than %d.\n",
5697 file, linenum, MAX_HDR_HISTORY);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005701 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005702 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005703
Willy Tarreau902636f2013-03-10 19:44:48 +01005704 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005705 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005706 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005707 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005708 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005709 goto out;
5710 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005711
5712 proto = protocol_by_family(sk->ss_family);
5713 if (!proto || !proto->connect) {
5714 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5715 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005716 err_code |= ERR_ALERT | ERR_FATAL;
5717 goto out;
5718 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005719
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005720 if (port1 != port2) {
5721 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5722 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
5725 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005726 curproxy->conn_src.tproxy_addr = *sk;
5727 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005728 }
5729 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005730#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005731 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005732#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005733#else /* no TPROXY support */
5734 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005735 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005738#endif
5739 cur_arg += 2;
5740 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005741 }
5742
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005743 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5744#ifdef SO_BINDTODEVICE
5745 if (!*args[cur_arg + 1]) {
5746 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005750 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005751 free(curproxy->conn_src.iface_name);
5752 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5753 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005754 global.last_checks |= LSTCHK_NETADM;
5755#else
5756 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5757 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005760#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005761 cur_arg += 2;
5762 continue;
5763 }
5764 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005765 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005770 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5771 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5772 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005775 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005777 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5779 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005783
5784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005785 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005786 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 }
5790 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005792 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005793 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
5797 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005799 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 }
5804 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005806 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005807 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810 }
5811 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005813 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005818 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005820 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005821 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005823 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005824 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005825 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005827 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005828 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005830 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005831 }
5832 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005834 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005835 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005837 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005840 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005846
5847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005848 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005849 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
5853 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005855 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005856 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
5860 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005862 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
5867 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005869 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005876 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005881 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005882 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005883 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005884 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005885 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005886 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005889 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005890
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 if (curproxy == &defproxy) {
5892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005893 err_code |= ERR_ALERT | ERR_FATAL;
5894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005896 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005897 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 if (*(args[1]) == 0) {
5900 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005901 err_code |= ERR_ALERT | ERR_FATAL;
5902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005904
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005905 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005906 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5907 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5908 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
5911 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005912 err_code |= warnif_cond_conflicts(cond,
5913 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5914 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005915 }
5916 else if (*args[2]) {
5917 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5918 file, linenum, args[0], args[2]);
5919 err_code |= ERR_ALERT | ERR_FATAL;
5920 goto out;
5921 }
5922
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005923 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005924 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005925 wl->s = strdup(args[1]);
5926 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005927 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 }
5929 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005930 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005935 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005936
Willy Tarreauade5ec42010-01-28 19:33:49 +01005937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005938 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005939 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 }
5943 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005945 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 }
5950 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005952 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005956 }
5957 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005958 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005961 err_code |= ERR_ALERT | ERR_FATAL;
5962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 }
5964
Willy Tarreauade5ec42010-01-28 19:33:49 +01005965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005966 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005967 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 }
5971 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005973 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 }
5978 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005980 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
5985 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005986 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005987
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 if (curproxy == &defproxy) {
5989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005992 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005993 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005994 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995
Willy Tarreaubaaee002006-06-26 02:48:02 +02005996 if (*(args[1]) == 0) {
5997 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006000 }
6001
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006002 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006003 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6004 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6005 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006009 err_code |= warnif_cond_conflicts(cond,
6010 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6011 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006012 }
6013 else if (*args[2]) {
6014 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6015 file, linenum, args[0], args[2]);
6016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
6018 }
6019
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006020 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006021 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006022 wl->s = strdup(args[1]);
6023 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 }
6025 else if (!strcmp(args[0], "errorloc") ||
6026 !strcmp(args[0], "errorloc302") ||
6027 !strcmp(args[0], "errorloc303")) { /* error location */
6028 int errnum, errlen;
6029 char *err;
6030
Willy Tarreau977b8e42006-12-29 14:19:17 +01006031 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006032 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006033
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006035 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006036 err_code |= ERR_ALERT | ERR_FATAL;
6037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 }
6039
6040 errnum = atol(args[1]);
6041 if (!strcmp(args[0], "errorloc303")) {
6042 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6043 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6044 } else {
6045 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6046 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6047 }
6048
Willy Tarreau0f772532006-12-23 20:51:41 +01006049 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6050 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006051 chunk_destroy(&curproxy->errmsg[rc]);
6052 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006053 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006056
6057 if (rc >= HTTP_ERR_SIZE) {
6058 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6059 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 free(err);
6061 }
6062 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006063 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6064 int errnum, errlen, fd;
6065 char *err;
6066 struct stat stat;
6067
6068 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006069 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006070
6071 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006072 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006073 err_code |= ERR_ALERT | ERR_FATAL;
6074 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006075 }
6076
6077 fd = open(args[2], O_RDONLY);
6078 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6079 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6080 file, linenum, args[2], args[1]);
6081 if (fd >= 0)
6082 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006083 err_code |= ERR_ALERT | ERR_FATAL;
6084 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006085 }
6086
Willy Tarreau27a674e2009-08-17 07:23:33 +02006087 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006088 errlen = stat.st_size;
6089 } else {
6090 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006091 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006092 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006093 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006094 }
6095
6096 err = malloc(errlen); /* malloc() must succeed during parsing */
6097 errnum = read(fd, err, errlen);
6098 if (errnum != errlen) {
6099 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6100 file, linenum, args[2], args[1]);
6101 close(fd);
6102 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006103 err_code |= ERR_ALERT | ERR_FATAL;
6104 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006105 }
6106 close(fd);
6107
6108 errnum = atol(args[1]);
6109 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6110 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006111 chunk_destroy(&curproxy->errmsg[rc]);
6112 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006113 break;
6114 }
6115 }
6116
6117 if (rc >= HTTP_ERR_SIZE) {
6118 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6119 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006120 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006121 free(err);
6122 }
6123 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006124 else if (!strcmp(args[0], "compression")) {
6125 struct comp *comp;
6126 if (curproxy->comp == NULL) {
6127 comp = calloc(1, sizeof(struct comp));
6128 curproxy->comp = comp;
6129 } else {
6130 comp = curproxy->comp;
6131 }
6132
6133 if (!strcmp(args[1], "algo")) {
6134 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006135 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006136
William Lallemand82fe75c2012-10-23 10:25:10 +02006137 cur_arg = 2;
6138 if (!*args[cur_arg]) {
6139 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6140 file, linenum, args[0]);
6141 err_code |= ERR_ALERT | ERR_FATAL;
6142 goto out;
6143 }
6144 while (*(args[cur_arg])) {
6145 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6146 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6147 file, linenum, args[0], args[cur_arg]);
6148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
6150 }
William Lallemand552df672012-11-07 13:21:47 +01006151 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6152 curproxy->comp->algos->end(&ctx);
6153 } else {
6154 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6155 file, linenum, args[0], args[cur_arg]);
6156 err_code |= ERR_ALERT | ERR_FATAL;
6157 goto out;
6158 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006159 cur_arg ++;
6160 continue;
6161 }
6162 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006163 else if (!strcmp(args[1], "offload")) {
6164 comp->offload = 1;
6165 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006166 else if (!strcmp(args[1], "type")) {
6167 int cur_arg;
6168 cur_arg = 2;
6169 if (!*args[cur_arg]) {
6170 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6171 file, linenum, args[0]);
6172 err_code |= ERR_ALERT | ERR_FATAL;
6173 goto out;
6174 }
6175 while (*(args[cur_arg])) {
6176 comp_append_type(comp, args[cur_arg]);
6177 cur_arg ++;
6178 continue;
6179 }
6180 }
6181 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006182 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006183 file, linenum, args[0]);
6184 err_code |= ERR_ALERT | ERR_FATAL;
6185 goto out;
6186 }
6187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006189 struct cfg_kw_list *kwl;
6190 int index;
6191
6192 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6193 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6194 if (kwl->kw[index].section != CFG_LISTEN)
6195 continue;
6196 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6197 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006198 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006199 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006200 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006201 err_code |= ERR_ALERT | ERR_FATAL;
6202 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006203 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006204 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006205 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006206 err_code |= ERR_WARN;
6207 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006208 }
Willy Tarreau93893792009-07-23 13:19:11 +02006209 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006210 }
6211 }
6212 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006213
Willy Tarreau6daf3432008-01-22 16:44:08 +01006214 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006215 err_code |= ERR_ALERT | ERR_FATAL;
6216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 }
Willy Tarreau93893792009-07-23 13:19:11 +02006218 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006219 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006220 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221}
6222
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006223int
6224cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6225{
6226
6227 int err_code = 0;
6228 const char *err;
6229
6230 if (!strcmp(args[0], "userlist")) { /* new userlist */
6231 struct userlist *newul;
6232
6233 if (!*args[1]) {
6234 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6235 file, linenum, args[0]);
6236 err_code |= ERR_ALERT | ERR_FATAL;
6237 goto out;
6238 }
6239
6240 err = invalid_char(args[1]);
6241 if (err) {
6242 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6243 file, linenum, *err, args[0], args[1]);
6244 err_code |= ERR_ALERT | ERR_FATAL;
6245 goto out;
6246 }
6247
6248 for (newul = userlist; newul; newul = newul->next)
6249 if (!strcmp(newul->name, args[1])) {
6250 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6251 file, linenum, args[1]);
6252 err_code |= ERR_WARN;
6253 goto out;
6254 }
6255
6256 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6257 if (!newul) {
6258 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6259 err_code |= ERR_ALERT | ERR_ABORT;
6260 goto out;
6261 }
6262
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006263 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006264 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006265 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6266 err_code |= ERR_ALERT | ERR_ABORT;
6267 goto out;
6268 }
6269
6270 newul->next = userlist;
6271 userlist = newul;
6272
6273 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006274 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006275 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006276 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006277
6278 if (!*args[1]) {
6279 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6280 file, linenum, args[0]);
6281 err_code |= ERR_ALERT | ERR_FATAL;
6282 goto out;
6283 }
6284
6285 err = invalid_char(args[1]);
6286 if (err) {
6287 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6288 file, linenum, *err, args[0], args[1]);
6289 err_code |= ERR_ALERT | ERR_FATAL;
6290 goto out;
6291 }
6292
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006293 for (ag = userlist->groups; ag; ag = ag->next)
6294 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006295 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6296 file, linenum, args[1], userlist->name);
6297 err_code |= ERR_ALERT;
6298 goto out;
6299 }
6300
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006301 ag = calloc(1, sizeof(*ag));
6302 if (!ag) {
6303 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6304 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006305 goto out;
6306 }
6307
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006308 ag->name = strdup(args[1]);
6309 if (!ag) {
6310 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6311 err_code |= ERR_ALERT | ERR_ABORT;
6312 goto out;
6313 }
6314
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006315 cur_arg = 2;
6316
6317 while (*args[cur_arg]) {
6318 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006319 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006320 cur_arg += 2;
6321 continue;
6322 } else {
6323 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6324 file, linenum, args[0]);
6325 err_code |= ERR_ALERT | ERR_FATAL;
6326 goto out;
6327 }
6328 }
6329
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006330 ag->next = userlist->groups;
6331 userlist->groups = ag;
6332
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006333 } else if (!strcmp(args[0], "user")) { /* new user */
6334 struct auth_users *newuser;
6335 int cur_arg;
6336
6337 if (!*args[1]) {
6338 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6339 file, linenum, args[0]);
6340 err_code |= ERR_ALERT | ERR_FATAL;
6341 goto out;
6342 }
6343
6344 for (newuser = userlist->users; newuser; newuser = newuser->next)
6345 if (!strcmp(newuser->user, args[1])) {
6346 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6347 file, linenum, args[1], userlist->name);
6348 err_code |= ERR_ALERT;
6349 goto out;
6350 }
6351
6352 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6353 if (!newuser) {
6354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6355 err_code |= ERR_ALERT | ERR_ABORT;
6356 goto out;
6357 }
6358
6359 newuser->user = strdup(args[1]);
6360
6361 newuser->next = userlist->users;
6362 userlist->users = newuser;
6363
6364 cur_arg = 2;
6365
6366 while (*args[cur_arg]) {
6367 if (!strcmp(args[cur_arg], "password")) {
6368#ifndef CONFIG_HAP_CRYPT
6369 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6370 file, linenum);
6371 err_code |= ERR_ALERT;
6372#endif
6373 newuser->pass = strdup(args[cur_arg + 1]);
6374 cur_arg += 2;
6375 continue;
6376 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6377 newuser->pass = strdup(args[cur_arg + 1]);
6378 newuser->flags |= AU_O_INSECURE;
6379 cur_arg += 2;
6380 continue;
6381 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006382 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006383 cur_arg += 2;
6384 continue;
6385 } else {
6386 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6387 file, linenum, args[0]);
6388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
6390 }
6391 }
6392 } else {
6393 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6394 err_code |= ERR_ALERT | ERR_FATAL;
6395 }
6396
6397out:
6398 return err_code;
6399}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400
6401/*
6402 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006403 * Returns the error code, 0 if OK, or any combination of :
6404 * - ERR_ABORT: must abort ASAP
6405 * - ERR_FATAL: we can continue parsing but not start the service
6406 * - ERR_WARN: a warning has been emitted
6407 * - ERR_ALERT: an alert has been emitted
6408 * Only the two first ones can stop processing, the two others are just
6409 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006410 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006411int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006413 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 FILE *f;
6415 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006416 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006417 struct cfg_section *cs = NULL;
6418 struct cfg_section *ics;
6419
6420 /* Register internal sections */
6421 if (!cfg_register_section("listen", cfg_parse_listen) ||
6422 !cfg_register_section("frontend", cfg_parse_listen) ||
6423 !cfg_register_section("backend", cfg_parse_listen) ||
6424 !cfg_register_section("ruleset", cfg_parse_listen) ||
6425 !cfg_register_section("defaults", cfg_parse_listen) ||
6426 !cfg_register_section("global", cfg_parse_global) ||
6427 !cfg_register_section("userlist", cfg_parse_users) ||
6428 !cfg_register_section("peers", cfg_parse_peers))
6429 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 if ((f=fopen(file,"r")) == NULL)
6432 return -1;
6433
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006434 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006435 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006436 char *end;
6437 char *args[MAX_LINE_ARGS + 1];
6438 char *line = thisline;
6439
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 linenum++;
6441
6442 end = line + strlen(line);
6443
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006444 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6445 /* Check if we reached the limit and the last char is not \n.
6446 * Watch out for the last line without the terminating '\n'!
6447 */
6448 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006449 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006450 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006451 }
6452
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006454 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 line++;
6456
6457 arg = 0;
6458 args[arg] = line;
6459
6460 while (*line && arg < MAX_LINE_ARGS) {
6461 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6462 * C equivalent value. Other combinations left unchanged (eg: \1).
6463 */
6464 if (*line == '\\') {
6465 int skip = 0;
6466 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6467 *line = line[1];
6468 skip = 1;
6469 }
6470 else if (line[1] == 'r') {
6471 *line = '\r';
6472 skip = 1;
6473 }
6474 else if (line[1] == 'n') {
6475 *line = '\n';
6476 skip = 1;
6477 }
6478 else if (line[1] == 't') {
6479 *line = '\t';
6480 skip = 1;
6481 }
6482 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006483 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 unsigned char hex1, hex2;
6485 hex1 = toupper(line[2]) - '0';
6486 hex2 = toupper(line[3]) - '0';
6487 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6488 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6489 *line = (hex1<<4) + hex2;
6490 skip = 3;
6491 }
6492 else {
6493 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006494 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006495 }
6496 }
6497 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006498 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 end -= skip;
6500 }
6501 line++;
6502 }
6503 else if (*line == '#' || *line == '\n' || *line == '\r') {
6504 /* end of string, end of loop */
6505 *line = 0;
6506 break;
6507 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006508 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006510 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006511 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 line++;
6513 args[++arg] = line;
6514 }
6515 else {
6516 line++;
6517 }
6518 }
6519
6520 /* empty line */
6521 if (!**args)
6522 continue;
6523
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006524 if (*line) {
6525 /* we had to stop due to too many args.
6526 * Let's terminate the string, print the offending part then cut the
6527 * last arg.
6528 */
6529 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6530 line++;
6531 *line = '\0';
6532
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006533 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006534 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006535 err_code |= ERR_ALERT | ERR_FATAL;
6536 args[arg] = line;
6537 }
6538
Willy Tarreau540abe42007-05-02 20:50:16 +02006539 /* zero out remaining args and ensure that at least one entry
6540 * is zeroed out.
6541 */
6542 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543 args[arg] = line;
6544 }
6545
Willy Tarreau3842f002009-06-14 11:39:52 +02006546 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006547 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006548 char *tmp;
6549
Willy Tarreau3842f002009-06-14 11:39:52 +02006550 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006551 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006552 for (arg=0; *args[arg+1]; arg++)
6553 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006554 *tmp = '\0'; // fix the next arg to \0
6555 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006556 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006557 else if (!strcmp(args[0], "default")) {
6558 kwm = KWM_DEF;
6559 for (arg=0; *args[arg+1]; arg++)
6560 args[arg] = args[arg+1]; // shift args after inversion
6561 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562
William Lallemand0f99e342011-10-12 17:50:54 +02006563 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6564 strcmp(args[0], "log") != 0) {
6565 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006566 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006567 }
6568
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006569 /* detect section start */
6570 list_for_each_entry(ics, &sections, list) {
6571 if (strcmp(args[0], ics->section_name) == 0) {
6572 cursection = ics->section_name;
6573 cs = ics;
6574 break;
6575 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006576 }
6577
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006579 if (cs)
6580 err_code |= cs->section_parser(file, linenum, args, kwm);
6581 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006582 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006583 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006585
6586 if (err_code & ERR_ABORT)
6587 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006589 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006591 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006592}
6593
Willy Tarreaubb925012009-07-23 13:36:36 +02006594/*
6595 * Returns the error code, 0 if OK, or any combination of :
6596 * - ERR_ABORT: must abort ASAP
6597 * - ERR_FATAL: we can continue parsing but not start the service
6598 * - ERR_WARN: a warning has been emitted
6599 * - ERR_ALERT: an alert has been emitted
6600 * Only the two first ones can stop processing, the two others are just
6601 * indicators.
6602 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006603int check_config_validity()
6604{
6605 int cfgerr = 0;
6606 struct proxy *curproxy = NULL;
6607 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006608 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006609 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006610 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006612 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006613 /*
6614 * Now, check for the integrity of all that we have collected.
6615 */
6616
6617 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006618 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006619
Willy Tarreau193b8c62012-11-22 00:17:38 +01006620 if (!global.tune.max_http_hdr)
6621 global.tune.max_http_hdr = MAX_HTTP_HDR;
6622
6623 if (!global.tune.cookie_len)
6624 global.tune.cookie_len = CAPTURE_LEN;
6625
6626 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6627
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006628 /* Post initialisation of the users and groups lists. */
6629 err_code = userlist_postinit();
6630 if (err_code != ERR_NONE)
6631 goto out;
6632
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006633 /* first, we will invert the proxy list order */
6634 curproxy = NULL;
6635 while (proxy) {
6636 struct proxy *next;
6637
6638 next = proxy->next;
6639 proxy->next = curproxy;
6640 curproxy = proxy;
6641 if (!next)
6642 break;
6643 proxy = next;
6644 }
6645
Willy Tarreaubaaee002006-06-26 02:48:02 +02006646 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006647 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006648 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006649 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006650 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006651 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006652 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006653 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006654
Willy Tarreau050536d2012-10-04 08:47:34 +02006655 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006656 /* proxy ID not set, use automatic numbering with first
6657 * spare entry starting with next_pxid.
6658 */
6659 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6660 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6661 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006662 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006663 next_pxid++;
6664
Willy Tarreau55ea7572007-06-17 19:56:27 +02006665
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006667 /* ensure we don't keep listeners uselessly bound */
6668 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006669 curproxy = curproxy->next;
6670 continue;
6671 }
6672
Willy Tarreau16a21472012-11-19 12:39:59 +01006673 /* number of processes this proxy is bound to */
6674 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6675
Willy Tarreauff01a212009-03-15 13:46:16 +01006676 switch (curproxy->mode) {
6677 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006678 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006679 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006680 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6681 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006682 cfgerr++;
6683 }
6684
6685 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006686 Warning("config : servers will be ignored for %s '%s'.\n",
6687 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006688 break;
6689
6690 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006691 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006692 break;
6693
6694 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006695 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006696 break;
6697 }
6698
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006699 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006700 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006701 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006702 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6703 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006704 cfgerr++;
6705 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006706#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006707 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006708 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6709 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006710 cfgerr++;
6711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006713 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006714 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6715 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006716 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006717 }
6718 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006719 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006720 /* If no LB algo is set in a backend, and we're not in
6721 * transparent mode, dispatch mode nor proxy mode, we
6722 * want to use balance roundrobin by default.
6723 */
6724 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6725 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006726 }
6727 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006728
Willy Tarreau1620ec32011-08-06 17:05:02 +02006729 if (curproxy->options & PR_O_DISPATCH)
6730 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6731 else if (curproxy->options & PR_O_HTTP_PROXY)
6732 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6733 else if (curproxy->options & PR_O_TRANSP)
6734 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006735
Willy Tarreau1620ec32011-08-06 17:05:02 +02006736 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6737 if (curproxy->options & PR_O_DISABLE404) {
6738 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6739 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6740 err_code |= ERR_WARN;
6741 curproxy->options &= ~PR_O_DISABLE404;
6742 }
6743 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6744 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6745 "send-state", proxy_type_str(curproxy), curproxy->id);
6746 err_code |= ERR_WARN;
6747 curproxy->options &= ~PR_O2_CHK_SNDST;
6748 }
Willy Tarreauef781042010-01-27 11:53:01 +01006749 }
6750
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006751 /* if a default backend was specified, let's find it */
6752 if (curproxy->defbe.name) {
6753 struct proxy *target;
6754
Alex Williams96532db2009-11-01 21:27:13 -05006755 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006756 if (!target) {
6757 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6758 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006759 cfgerr++;
6760 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006761 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6762 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006763 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006764 } else {
6765 free(curproxy->defbe.name);
6766 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006767 /* we force the backend to be present on at least all of
6768 * the frontend's processes.
6769 */
6770 target->bind_proc = curproxy->bind_proc ?
6771 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006772
6773 /* Emit a warning if this proxy also has some servers */
6774 if (curproxy->srv) {
6775 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6776 curproxy->id);
6777 err_code |= ERR_WARN;
6778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006779 }
6780 }
6781
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006782 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006783 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6784 /* map jump target for ACT_SETBE in req_rep chain */
6785 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006786 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006787 struct proxy *target;
6788
Willy Tarreaua496b602006-12-17 23:15:24 +01006789 if (exp->action != ACT_SETBE)
6790 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006791
Alex Williams96532db2009-11-01 21:27:13 -05006792 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006793 if (!target) {
6794 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6795 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006796 cfgerr++;
6797 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006798 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6799 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006800 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006801 } else {
6802 free((void *)exp->replace);
6803 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006804 /* we force the backend to be present on at least all of
6805 * the frontend's processes.
6806 */
6807 target->bind_proc = curproxy->bind_proc ?
6808 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006809 }
6810 }
6811 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006812
6813 /* find the target proxy for 'use_backend' rules */
6814 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006815 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006816 struct logformat_node *node;
6817 char *pxname;
6818
6819 /* Try to parse the string as a log format expression. If the result
6820 * of the parsing is only one entry containing a simple string, then
6821 * it's a standard string corresponding to a static rule, thus the
6822 * parsing is cancelled and be.name is restored to be resolved.
6823 */
6824 pxname = rule->be.name;
6825 LIST_INIT(&rule->be.expr);
6826 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6827 curproxy->conf.args.file, curproxy->conf.args.line);
6828 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6829
6830 if (!LIST_ISEMPTY(&rule->be.expr)) {
6831 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6832 rule->dynamic = 1;
6833 free(pxname);
6834 continue;
6835 }
6836 /* simple string: free the expression and fall back to static rule */
6837 free(node->arg);
6838 free(node);
6839 }
6840
6841 rule->dynamic = 0;
6842 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006843
Alex Williams96532db2009-11-01 21:27:13 -05006844 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006845
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006846 if (!target) {
6847 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6848 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006849 cfgerr++;
6850 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006851 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6852 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006853 cfgerr++;
6854 } else {
6855 free((void *)rule->be.name);
6856 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006857 /* we force the backend to be present on at least all of
6858 * the frontend's processes.
6859 */
6860 target->bind_proc = curproxy->bind_proc ?
6861 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006862 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006863 }
6864
6865 /* find the target proxy for 'use_backend' rules */
6866 list_for_each_entry(srule, &curproxy->server_rules, list) {
6867 struct server *target = findserver(curproxy, srule->srv.name);
6868
6869 if (!target) {
6870 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6871 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6872 cfgerr++;
6873 continue;
6874 }
6875 free((void *)srule->srv.name);
6876 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006877 }
6878
Emeric Brunb982a3d2010-01-04 15:45:53 +01006879 /* find the target table for 'stick' rules */
6880 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6881 struct proxy *target;
6882
Emeric Brun1d33b292010-01-04 15:47:17 +01006883 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6884 if (mrule->flags & STK_IS_STORE)
6885 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6886
Emeric Brunb982a3d2010-01-04 15:45:53 +01006887 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006888 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006889 else
6890 target = curproxy;
6891
6892 if (!target) {
6893 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6894 curproxy->id, mrule->table.name);
6895 cfgerr++;
6896 }
6897 else if (target->table.size == 0) {
6898 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6899 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6900 cfgerr++;
6901 }
Willy Tarreau12785782012-04-27 21:37:17 +02006902 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6903 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006904 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6905 cfgerr++;
6906 }
6907 else {
6908 free((void *)mrule->table.name);
6909 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006910 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006911 }
6912 }
6913
6914 /* find the target table for 'store response' rules */
6915 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6916 struct proxy *target;
6917
Emeric Brun1d33b292010-01-04 15:47:17 +01006918 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6919
Emeric Brunb982a3d2010-01-04 15:45:53 +01006920 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006921 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006922 else
6923 target = curproxy;
6924
6925 if (!target) {
6926 Alert("Proxy '%s': unable to find store table '%s'.\n",
6927 curproxy->id, mrule->table.name);
6928 cfgerr++;
6929 }
6930 else if (target->table.size == 0) {
6931 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6932 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6933 cfgerr++;
6934 }
Willy Tarreau12785782012-04-27 21:37:17 +02006935 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6936 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006937 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6938 cfgerr++;
6939 }
6940 else {
6941 free((void *)mrule->table.name);
6942 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006943 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006944 }
6945 }
6946
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006947 /* find the target table for 'tcp-request' layer 4 rules */
6948 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6949 struct proxy *target;
6950
Willy Tarreaub4c84932013-07-23 19:15:30 +02006951 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006952 continue;
6953
6954 if (trule->act_prm.trk_ctr.table.n)
6955 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6956 else
6957 target = curproxy;
6958
6959 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006960 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6961 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006962 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006963 cfgerr++;
6964 }
6965 else if (target->table.size == 0) {
6966 Alert("Proxy '%s': table '%s' used but not configured.\n",
6967 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6968 cfgerr++;
6969 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006970 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6971 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6972 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 +01006973 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006974 cfgerr++;
6975 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006976 else {
6977 free(trule->act_prm.trk_ctr.table.n);
6978 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006979 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006980 * to pass a list of counters to track and allocate them right here using
6981 * stktable_alloc_data_type().
6982 */
6983 }
6984 }
6985
Willy Tarreaud1f96522010-08-03 19:34:32 +02006986 /* find the target table for 'tcp-request' layer 6 rules */
6987 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6988 struct proxy *target;
6989
Willy Tarreaub4c84932013-07-23 19:15:30 +02006990 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006991 continue;
6992
6993 if (trule->act_prm.trk_ctr.table.n)
6994 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6995 else
6996 target = curproxy;
6997
6998 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006999 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7000 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007001 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007002 cfgerr++;
7003 }
7004 else if (target->table.size == 0) {
7005 Alert("Proxy '%s': table '%s' used but not configured.\n",
7006 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7007 cfgerr++;
7008 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007009 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7010 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7011 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 +01007012 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007013 cfgerr++;
7014 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007015 else {
7016 free(trule->act_prm.trk_ctr.table.n);
7017 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007018 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007019 * to pass a list of counters to track and allocate them right here using
7020 * stktable_alloc_data_type().
7021 */
7022 }
7023 }
7024
Emeric Brun32da3c42010-09-23 18:39:19 +02007025 if (curproxy->table.peers.name) {
7026 struct peers *curpeers = peers;
7027
7028 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7029 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7030 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007031 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007032 break;
7033 }
7034 }
7035
7036 if (!curpeers) {
7037 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7038 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007039 free((void *)curproxy->table.peers.name);
7040 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007041 cfgerr++;
7042 }
7043 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007044 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7045 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007046 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007047 cfgerr++;
7048 }
7049 }
7050
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007051 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007052 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007053 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7054 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7055 "proxy", curproxy->id);
7056 cfgerr++;
7057 goto out_uri_auth_compat;
7058 }
7059
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007060 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007061 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007062 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007063 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007064
Willy Tarreau95fa4692010-02-01 13:05:50 +01007065 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7066 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007067
7068 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007069 uri_auth_compat_req[i++] = "realm";
7070 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7071 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007072
Willy Tarreau95fa4692010-02-01 13:05:50 +01007073 uri_auth_compat_req[i++] = "unless";
7074 uri_auth_compat_req[i++] = "{";
7075 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7076 uri_auth_compat_req[i++] = "}";
7077 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007078
Willy Tarreauff011f22011-01-06 17:51:27 +01007079 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7080 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007081 cfgerr++;
7082 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007083 }
7084
Willy Tarreauff011f22011-01-06 17:51:27 +01007085 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007086
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007087 if (curproxy->uri_auth->auth_realm) {
7088 free(curproxy->uri_auth->auth_realm);
7089 curproxy->uri_auth->auth_realm = NULL;
7090 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007091
7092 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007093 }
7094out_uri_auth_compat:
7095
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007096 /* compile the log format */
7097 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007098 if (curproxy->conf.logformat_string != default_http_log_format &&
7099 curproxy->conf.logformat_string != default_tcp_log_format &&
7100 curproxy->conf.logformat_string != clf_http_log_format)
7101 free(curproxy->conf.logformat_string);
7102 curproxy->conf.logformat_string = NULL;
7103 free(curproxy->conf.lfs_file);
7104 curproxy->conf.lfs_file = NULL;
7105 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007106 }
7107
Willy Tarreau62a61232013-04-12 18:13:46 +02007108 if (curproxy->conf.logformat_string) {
7109 curproxy->conf.args.ctx = ARGC_LOG;
7110 curproxy->conf.args.file = curproxy->conf.lfs_file;
7111 curproxy->conf.args.line = curproxy->conf.lfs_line;
7112 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007113 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007114 curproxy->conf.args.file = NULL;
7115 curproxy->conf.args.line = 0;
7116 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007117
Willy Tarreau62a61232013-04-12 18:13:46 +02007118 if (curproxy->conf.uniqueid_format_string) {
7119 curproxy->conf.args.ctx = ARGC_UIF;
7120 curproxy->conf.args.file = curproxy->conf.uif_file;
7121 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007122 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007123 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
7124 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007125 curproxy->conf.args.file = NULL;
7126 curproxy->conf.args.line = 0;
7127 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007128
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007129 /* only now we can check if some args remain unresolved.
7130 * This must be done after the users and groups resolution.
7131 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007132 cfgerr += smp_resolve_args(curproxy);
7133 if (!cfgerr)
7134 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007135
Willy Tarreau2738a142006-07-08 17:28:09 +02007136 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007137 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007138 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007139 (!curproxy->timeout.connect ||
7140 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007141 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007142 " | While not properly invalid, you will certainly encounter various problems\n"
7143 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007144 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007145 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007146 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007147 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007148
Willy Tarreau1fa31262007-12-03 00:36:16 +01007149 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7150 * We must still support older configurations, so let's find out whether those
7151 * parameters have been set or must be copied from contimeouts.
7152 */
7153 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007154 if (!curproxy->timeout.tarpit ||
7155 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007156 /* tarpit timeout not set. We search in the following order:
7157 * default.tarpit, curr.connect, default.connect.
7158 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007159 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007160 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007161 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007162 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007163 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007164 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007165 }
7166 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007167 (!curproxy->timeout.queue ||
7168 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007169 /* queue timeout not set. We search in the following order:
7170 * default.queue, curr.connect, default.connect.
7171 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007172 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007173 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007174 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007175 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007176 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007177 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007178 }
7179 }
7180
Willy Tarreau1620ec32011-08-06 17:05:02 +02007181 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007182 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7183 curproxy->check_req = (char *)malloc(curproxy->check_len);
7184 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007185 }
7186
Willy Tarreau193b8c62012-11-22 00:17:38 +01007187 /* ensure that cookie capture length is not too large */
7188 if (curproxy->capture_len >= global.tune.cookie_len) {
7189 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7190 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7191 err_code |= ERR_WARN;
7192 curproxy->capture_len = global.tune.cookie_len - 1;
7193 }
7194
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007195 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007196 if (curproxy->nb_req_cap) {
7197 if (curproxy->mode == PR_MODE_HTTP) {
7198 curproxy->req_cap_pool = create_pool("ptrcap",
7199 curproxy->nb_req_cap * sizeof(char *),
7200 MEM_F_SHARED);
7201 } else {
7202 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7203 proxy_type_str(curproxy), curproxy->id);
7204 err_code |= ERR_WARN;
7205 curproxy->to_log &= ~LW_REQHDR;
7206 curproxy->nb_req_cap = 0;
7207 }
7208 }
7209
7210 if (curproxy->nb_rsp_cap) {
7211 if (curproxy->mode == PR_MODE_HTTP) {
7212 curproxy->rsp_cap_pool = create_pool("ptrcap",
7213 curproxy->nb_rsp_cap * sizeof(char *),
7214 MEM_F_SHARED);
7215 } else {
7216 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7217 proxy_type_str(curproxy), curproxy->id);
7218 err_code |= ERR_WARN;
7219 curproxy->to_log &= ~LW_REQHDR;
7220 curproxy->nb_rsp_cap = 0;
7221 }
7222 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007223
Willy Tarreaubaaee002006-06-26 02:48:02 +02007224 /* first, we will invert the servers list order */
7225 newsrv = NULL;
7226 while (curproxy->srv) {
7227 struct server *next;
7228
7229 next = curproxy->srv->next;
7230 curproxy->srv->next = newsrv;
7231 newsrv = curproxy->srv;
7232 if (!next)
7233 break;
7234 curproxy->srv = next;
7235 }
7236
Willy Tarreau17edc812014-01-03 12:14:34 +01007237 /* Check that no server name conflicts. This causes trouble in the stats.
7238 * We only emit a warning for the first conflict affecting each server,
7239 * in order to avoid combinatory explosion if all servers have the same
7240 * name. We do that only for servers which do not have an explicit ID,
7241 * because these IDs were made also for distinguishing them and we don't
7242 * want to annoy people who correctly manage them.
7243 */
7244 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7245 struct server *other_srv;
7246
7247 if (newsrv->puid)
7248 continue;
7249
7250 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7251 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7252 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7253 newsrv->conf.file, newsrv->conf.line,
7254 proxy_type_str(curproxy), curproxy->id,
7255 newsrv->id, other_srv->conf.line);
7256 break;
7257 }
7258 }
7259 }
7260
Willy Tarreaudd701652010-05-25 23:03:02 +02007261 /* assign automatic UIDs to servers which don't have one yet */
7262 next_id = 1;
7263 newsrv = curproxy->srv;
7264 while (newsrv != NULL) {
7265 if (!newsrv->puid) {
7266 /* server ID not set, use automatic numbering with first
7267 * spare entry starting with next_svid.
7268 */
7269 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7270 newsrv->conf.id.key = newsrv->puid = next_id;
7271 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7272 }
7273 next_id++;
7274 newsrv = newsrv->next;
7275 }
7276
Willy Tarreau20697042007-11-15 23:26:18 +01007277 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007278 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007279
Willy Tarreau62c3be22012-01-20 13:12:32 +01007280 /*
7281 * If this server supports a maxconn parameter, it needs a dedicated
7282 * tasks to fill the emptied slots when a connection leaves.
7283 * Also, resolve deferred tracking dependency if needed.
7284 */
7285 newsrv = curproxy->srv;
7286 while (newsrv != NULL) {
7287 if (newsrv->minconn > newsrv->maxconn) {
7288 /* Only 'minconn' was specified, or it was higher than or equal
7289 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7290 * this will avoid further useless expensive computations.
7291 */
7292 newsrv->maxconn = newsrv->minconn;
7293 } else if (newsrv->maxconn && !newsrv->minconn) {
7294 /* minconn was not specified, so we set it to maxconn */
7295 newsrv->minconn = newsrv->maxconn;
7296 }
7297
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007298#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007299 if (newsrv->use_ssl || newsrv->check.use_ssl)
7300 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007301#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007302
Willy Tarreau2f075e92013-12-03 11:11:34 +01007303 /* set the check type on the server */
7304 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7305
Willy Tarreau62c3be22012-01-20 13:12:32 +01007306 if (newsrv->trackit) {
7307 struct proxy *px;
7308 struct server *srv;
7309 char *pname, *sname;
7310
7311 pname = newsrv->trackit;
7312 sname = strrchr(pname, '/');
7313
7314 if (sname)
7315 *sname++ = '\0';
7316 else {
7317 sname = pname;
7318 pname = NULL;
7319 }
7320
7321 if (pname) {
7322 px = findproxy(pname, PR_CAP_BE);
7323 if (!px) {
7324 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7325 proxy_type_str(curproxy), curproxy->id,
7326 newsrv->id, pname);
7327 cfgerr++;
7328 goto next_srv;
7329 }
7330 } else
7331 px = curproxy;
7332
7333 srv = findserver(px, sname);
7334 if (!srv) {
7335 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7336 proxy_type_str(curproxy), curproxy->id,
7337 newsrv->id, sname);
7338 cfgerr++;
7339 goto next_srv;
7340 }
7341
Willy Tarreauff5ae352013-12-11 20:36:34 +01007342 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007343 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7344 "tracking as it does not have checks enabled.\n",
7345 proxy_type_str(curproxy), curproxy->id,
7346 newsrv->id, px->id, srv->id);
7347 cfgerr++;
7348 goto next_srv;
7349 }
7350
7351 if (curproxy != px &&
7352 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7353 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7354 "tracking: disable-on-404 option inconsistency.\n",
7355 proxy_type_str(curproxy), curproxy->id,
7356 newsrv->id, px->id, srv->id);
7357 cfgerr++;
7358 goto next_srv;
7359 }
7360
7361 /* if the other server is forced disabled, we have to do the same here */
7362 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007363 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007364 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007365 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007366 }
7367
7368 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007369 newsrv->tracknext = srv->trackers;
7370 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007371
7372 free(newsrv->trackit);
7373 newsrv->trackit = NULL;
7374 }
7375 next_srv:
7376 newsrv = newsrv->next;
7377 }
7378
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007379 /* We have to initialize the server lookup mechanism depending
7380 * on what LB algorithm was choosen.
7381 */
7382
7383 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7384 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7385 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007386 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7387 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7388 init_server_map(curproxy);
7389 } else {
7390 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7391 fwrr_init_server_groups(curproxy);
7392 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007393 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007394
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007395 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007396 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7397 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7398 fwlc_init_server_tree(curproxy);
7399 } else {
7400 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7401 fas_init_server_tree(curproxy);
7402 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007403 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007404
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007405 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007406 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7407 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7408 chash_init_server_tree(curproxy);
7409 } else {
7410 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7411 init_server_map(curproxy);
7412 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007413 break;
7414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007415
7416 if (curproxy->options & PR_O_LOGASAP)
7417 curproxy->to_log &= ~LW_BYTES;
7418
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007419 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007420 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007421 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7422 proxy_type_str(curproxy), curproxy->id);
7423 err_code |= ERR_WARN;
7424 }
7425
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007426 if (curproxy->mode != PR_MODE_HTTP) {
7427 int optnum;
7428
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007429 if (curproxy->uri_auth) {
7430 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7431 proxy_type_str(curproxy), curproxy->id);
7432 err_code |= ERR_WARN;
7433 curproxy->uri_auth = NULL;
7434 }
7435
Willy Tarreau87cf5142011-08-19 22:57:24 +02007436 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007437 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7438 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7439 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007440 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007441 }
7442
7443 if (curproxy->options & PR_O_ORGTO) {
7444 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7445 "originalto", proxy_type_str(curproxy), curproxy->id);
7446 err_code |= ERR_WARN;
7447 curproxy->options &= ~PR_O_ORGTO;
7448 }
7449
7450 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7451 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7452 (curproxy->cap & cfg_opts[optnum].cap) &&
7453 (curproxy->options & cfg_opts[optnum].val)) {
7454 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7455 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7456 err_code |= ERR_WARN;
7457 curproxy->options &= ~cfg_opts[optnum].val;
7458 }
7459 }
7460
7461 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7462 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7463 (curproxy->cap & cfg_opts2[optnum].cap) &&
7464 (curproxy->options2 & cfg_opts2[optnum].val)) {
7465 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7466 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7467 err_code |= ERR_WARN;
7468 curproxy->options2 &= ~cfg_opts2[optnum].val;
7469 }
7470 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007471
Pieter Baauwd551fb52013-05-08 22:49:23 +02007472#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007473 if (curproxy->conn_src.bind_hdr_occ) {
7474 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007475 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007476 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007477 err_code |= ERR_WARN;
7478 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007479#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007480 }
7481
Willy Tarreaubaaee002006-06-26 02:48:02 +02007482 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007483 * ensure that we're not cross-dressing a TCP server into HTTP.
7484 */
7485 newsrv = curproxy->srv;
7486 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007487 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007488 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7489 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007490 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007491 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007492
Willy Tarreau0cec3312011-10-31 13:49:26 +01007493 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7494 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7495 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7496 err_code |= ERR_WARN;
7497 }
7498
Willy Tarreau82ffa392013-08-13 17:19:08 +02007499 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7500 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7501 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7502 err_code |= ERR_WARN;
7503 }
7504
Pieter Baauwd551fb52013-05-08 22:49:23 +02007505#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007506 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7507 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007508 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 +01007509 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007510 err_code |= ERR_WARN;
7511 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007512#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007513 newsrv = newsrv->next;
7514 }
7515
Willy Tarreauc1a21672009-08-16 22:37:44 +02007516 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007517 if (!curproxy->accept)
7518 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007519
Willy Tarreauc1a21672009-08-16 22:37:44 +02007520 if (curproxy->tcp_req.inspect_delay ||
7521 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007522 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007523
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007524 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007525 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007526 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007527 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007528
7529 /* both TCP and HTTP must check switching rules */
7530 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7531 }
7532
7533 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007534 if (curproxy->tcp_req.inspect_delay ||
7535 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7536 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7537
Emeric Brun97679e72010-09-23 17:56:44 +02007538 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7539 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7540
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007541 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007542 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007543 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007544 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007545
7546 /* If the backend does requires RDP cookie persistence, we have to
7547 * enable the corresponding analyser.
7548 */
7549 if (curproxy->options2 & PR_O2_RDPC_PRST)
7550 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7551 }
7552
Emeric Brunc52962f2012-11-15 18:28:02 +01007553#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007554 /* Configure SSL for each bind line.
7555 * Note: if configuration fails at some point, the ->ctx member
7556 * remains NULL so that listeners can later detach.
7557 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007558 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007559 if (!bind_conf->is_ssl) {
7560 if (bind_conf->default_ctx) {
7561 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7562 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7563 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007564 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007565 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007566 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007567 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007568 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007569 cfgerr++;
7570 continue;
7571 }
7572
Emeric Brun4b3091e2012-09-24 15:48:52 +02007573 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007574 Alert("Unable to allocate SSL session cache.\n");
7575 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007576 continue;
7577 }
7578
Emeric Brunfc0421f2012-09-07 17:30:07 +02007579 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007580 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007581 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007582#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007583
Willy Tarreaue6b98942007-10-29 01:09:36 +01007584 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007585 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007586 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007587 if (!listener->luid) {
7588 /* listener ID not set, use automatic numbering with first
7589 * spare entry starting with next_luid.
7590 */
7591 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7592 listener->conf.id.key = listener->luid = next_id;
7593 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007594 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007595 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007596
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007597 /* enable separate counters */
7598 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7599 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007600 if (!listener->name)
7601 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007602 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007603
Willy Tarreaue6b98942007-10-29 01:09:36 +01007604 if (curproxy->options & PR_O_TCP_NOLING)
7605 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007606 if (!listener->maxconn)
7607 listener->maxconn = curproxy->maxconn;
7608 if (!listener->backlog)
7609 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007610 if (!listener->maxaccept)
7611 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7612
7613 /* we want to have an optimal behaviour on single process mode to
7614 * maximize the work at once, but in multi-process we want to keep
7615 * some fairness between processes, so we target half of the max
7616 * number of events to be balanced over all the processes the proxy
7617 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7618 * used to disable the limit.
7619 */
7620 if (listener->maxaccept > 0) {
7621 if (nbproc > 1)
7622 listener->maxaccept = (listener->maxaccept + 1) / 2;
7623 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7624 }
7625
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007626 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007627 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007628 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007629 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007630
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007631 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7632 listener->options |= LI_O_TCP_RULES;
7633
Willy Tarreaude3041d2010-05-31 10:56:17 +02007634 if (curproxy->mon_mask.s_addr)
7635 listener->options |= LI_O_CHK_MONNET;
7636
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007637 /* smart accept mode is automatic in HTTP mode */
7638 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007639 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007640 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7641 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007642 }
7643
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007644 /* Release unused SSL configs */
7645 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7646 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007647 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007648#ifdef USE_OPENSSL
7649 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007650 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007651 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007652 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007653 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007654#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007655 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007656
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007657 /* Check multi-process mode compatibility for the current proxy */
7658 if (global.nbproc > 1) {
7659 int nbproc = 0;
7660 if (curproxy->bind_proc) {
7661 int proc;
7662 for (proc = 0; proc < global.nbproc; proc++) {
7663 if (curproxy->bind_proc & (1 << proc)) {
7664 nbproc++;
7665 }
7666 }
7667 } else {
7668 nbproc = global.nbproc;
7669 }
7670 if (curproxy->table.peers.name) {
7671 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7672 curproxy->id);
7673 cfgerr++;
7674 }
7675 if (nbproc > 1) {
7676 if (curproxy->uri_auth) {
7677 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7678 curproxy->id);
7679 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7680 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7681 curproxy->id);
7682 }
7683 }
7684 if (curproxy->appsession_name) {
7685 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7686 curproxy->id);
7687 }
7688 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7689 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7690 curproxy->id);
7691 }
7692 }
7693 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007694
7695 /* create the task associated with the proxy */
7696 curproxy->task = task_new();
7697 if (curproxy->task) {
7698 curproxy->task->context = curproxy;
7699 curproxy->task->process = manage_proxy;
7700 /* no need to queue, it will be done automatically if some
7701 * listener gets limited.
7702 */
7703 curproxy->task->expire = TICK_ETERNITY;
7704 } else {
7705 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7706 curproxy->id);
7707 cfgerr++;
7708 }
7709
Willy Tarreaubaaee002006-06-26 02:48:02 +02007710 curproxy = curproxy->next;
7711 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007712
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007713 /* Check multi-process mode compatibility */
7714 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007715 if (global.stats_fe && !global.stats_fe->bind_proc) {
7716 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 +01007717 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007718 }
7719
7720 /* automatically compute fullconn if not set. We must not do it in the
7721 * loop above because cross-references are not yet fully resolved.
7722 */
7723 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7724 /* If <fullconn> is not set, let's set it to 10% of the sum of
7725 * the possible incoming frontend's maxconns.
7726 */
7727 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7728 struct proxy *fe;
7729 int total = 0;
7730
7731 /* sum up the number of maxconns of frontends which
7732 * reference this backend at least once or which are
7733 * the same one ('listen').
7734 */
7735 for (fe = proxy; fe; fe = fe->next) {
7736 struct switching_rule *rule;
7737 struct hdr_exp *exp;
7738 int found = 0;
7739
7740 if (!(fe->cap & PR_CAP_FE))
7741 continue;
7742
7743 if (fe == curproxy) /* we're on a "listen" instance */
7744 found = 1;
7745
7746 if (fe->defbe.be == curproxy) /* "default_backend" */
7747 found = 1;
7748
7749 /* check if a "use_backend" rule matches */
7750 if (!found) {
7751 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007752 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007753 found = 1;
7754 break;
7755 }
7756 }
7757 }
7758
7759 /* check if a "reqsetbe" rule matches */
7760 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7761 if (exp->action == ACT_SETBE &&
7762 (struct proxy *)exp->replace == curproxy) {
7763 found = 1;
7764 break;
7765 }
7766 }
7767
7768 /* now we've checked all possible ways to reference a backend
7769 * from a frontend.
7770 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007771 if (!found)
7772 continue;
7773 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007774 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007775 /* we have the sum of the maxconns in <total>. We only
7776 * keep 10% of that sum to set the default fullconn, with
7777 * a hard minimum of 1 (to avoid a divide by zero).
7778 */
7779 curproxy->fullconn = (total + 9) / 10;
7780 if (!curproxy->fullconn)
7781 curproxy->fullconn = 1;
7782 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007783 }
7784
Willy Tarreau056f5682010-06-06 15:51:11 +02007785 /* initialize stick-tables on backend capable proxies. This must not
7786 * be done earlier because the data size may be discovered while parsing
7787 * other proxies.
7788 */
Godbach9703e662013-12-11 21:11:41 +08007789 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007790 if (curproxy->state == PR_STSTOPPED)
7791 continue;
7792
Godbach9703e662013-12-11 21:11:41 +08007793 if (!stktable_init(&curproxy->table)) {
7794 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7795 cfgerr++;
7796 }
7797 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007798
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007799 /*
7800 * Recount currently required checks.
7801 */
7802
7803 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7804 int optnum;
7805
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007806 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7807 if (curproxy->options & cfg_opts[optnum].val)
7808 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007809
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007810 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7811 if (curproxy->options2 & cfg_opts2[optnum].val)
7812 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007813 }
7814
Willy Tarreau122541c2011-09-07 21:24:49 +02007815 if (peers) {
7816 struct peers *curpeers = peers, **last;
7817 struct peer *p, *pb;
7818
7819 /* Remove all peers sections which don't have a valid listener.
7820 * This can happen when a peers section is never referenced and
7821 * does not contain a local peer.
7822 */
7823 last = &peers;
7824 while (*last) {
7825 curpeers = *last;
7826 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007827 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007828 last = &curpeers->next;
7829 continue;
7830 }
7831
7832 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7833 curpeers->id, localpeer);
7834
7835 p = curpeers->remote;
7836 while (p) {
7837 pb = p->next;
7838 free(p->id);
7839 free(p);
7840 p = pb;
7841 }
7842
7843 /* Destroy and unlink this curpeers section.
7844 * Note: curpeers is backed up into *last.
7845 */
7846 free(curpeers->id);
7847 curpeers = curpeers->next;
7848 free(*last);
7849 *last = curpeers;
7850 }
7851 }
7852
Willy Tarreau34eb6712011-10-24 18:15:04 +02007853 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007854 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007855 MEM_F_SHARED);
7856
Willy Tarreaubb925012009-07-23 13:36:36 +02007857 if (cfgerr > 0)
7858 err_code |= ERR_ALERT | ERR_FATAL;
7859 out:
7860 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007861}
7862
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007863/*
7864 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7865 * parsing sessions.
7866 */
7867void cfg_register_keywords(struct cfg_kw_list *kwl)
7868{
7869 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7870}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007871
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007872/*
7873 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7874 */
7875void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7876{
7877 LIST_DEL(&kwl->list);
7878 LIST_INIT(&kwl->list);
7879}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007880
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007881/* this function register new section in the haproxy configuration file.
7882 * <section_name> is the name of this new section and <section_parser>
7883 * is the called parser. If two section declaration have the same name,
7884 * only the first declared is used.
7885 */
7886int cfg_register_section(char *section_name,
7887 int (*section_parser)(const char *, int, char **, int))
7888{
7889 struct cfg_section *cs;
7890
7891 cs = calloc(1, sizeof(*cs));
7892 if (!cs) {
7893 Alert("register section '%s': out of memory.\n", section_name);
7894 return 0;
7895 }
7896
7897 cs->section_name = section_name;
7898 cs->section_parser = section_parser;
7899
7900 LIST_ADDQ(&sections, &cs->list);
7901
7902 return 1;
7903}
7904
Willy Tarreaubaaee002006-06-26 02:48:02 +02007905/*
7906 * Local variables:
7907 * c-indent-level: 8
7908 * c-basic-offset: 8
7909 * End:
7910 */