blob: 3bc700be0c97c39f8cd9ca4280a3f49521a94129 [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
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int 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 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100210 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211
212 str = next;
213 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100214 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 *next++ = 0;
216 }
217
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100218 ss2 = str2sa_range(str, &port, &end, err,
219 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
220 if (!ss2)
221 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100223 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100224 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100229 if (!port || !end) {
230 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
231 goto fail;
232 }
233
Emeric Bruned760922010-10-22 17:59:25 +0200234 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200235 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200236 goto fail;
237 }
238
239 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200240 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200241 goto fail;
242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100244 else if (ss2->ss_family == AF_UNSPEC) {
245 socklen_t addr_len;
246
247 /* We want to attach to an already bound fd whose number
248 * is in the addr part of ss2 when cast to sockaddr_in.
249 * Note that by definition there is a single listener.
250 * We still have to determine the address family to
251 * register the correct protocol.
252 */
253 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
254 addr_len = sizeof(*ss2);
255 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
256 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
257 goto fail;
258 }
259
260 port = end = get_host_port(ss2);
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100263 /* OK the address looks correct */
264 ss = *ss2;
265
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100268 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200269 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
270 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
271 l->frontend = curproxy;
272 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273
Willy Tarreau40aa0702013-03-10 23:51:38 +0100274 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200275 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200276 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100277 l->state = LI_INIT;
278
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100279 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200280 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 tcpv4_add_listener(l);
282 }
Emeric Bruned760922010-10-22 17:59:25 +0200283 else if (ss.ss_family == AF_INET6) {
284 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
285 tcpv6_add_listener(l);
286 }
287 else {
Emeric Bruned760922010-10-22 17:59:25 +0200288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100417/* Report it if a request ACL condition uses some keywords that are incompatible
418 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
419 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
420 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100421 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100422static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200425 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100428 return 0;
429
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100430 acl = acl_cond_conflicts(cond, where);
431 if (acl) {
432 if (acl->name && *acl->name)
433 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
434 file, line, acl->name, sample_ckp_names(where));
435 else
436 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 +0200437 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100438 return ERR_WARN;
439 }
440 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100441 return 0;
442
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 if (acl->name && *acl->name)
444 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100446 else
447 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200448 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100449 return ERR_WARN;
450}
451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200471 else if (!strcmp(args[0], "ca-base")) {
472#ifdef USE_OPENSSL
473 if (global.ca_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.ca_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
490 else if (!strcmp(args[0], "crt-base")) {
491#ifdef USE_OPENSSL
492 if (global.crt_base != NULL) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.crt_base = strdup(args[1]);
503#else
504 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507#endif
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509 else if (!strcmp(args[0], "daemon")) {
510 global.mode |= MODE_DAEMON;
511 }
512 else if (!strcmp(args[0], "debug")) {
513 global.mode |= MODE_DEBUG;
514 }
515 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200518 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200521 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100524 else if (!strcmp(args[0], "nosplice")) {
525 global.tune.options &= ~GTUNE_USE_SPLICE;
526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "quiet")) {
528 global.mode |= MODE_QUIET;
529 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200530 else if (!strcmp(args[0], "tune.maxpollevents")) {
531 if (global.tune.maxpollevents != 0) {
532 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200540 }
541 global.tune.maxpollevents = atol(args[1]);
542 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100543 else if (!strcmp(args[0], "tune.maxaccept")) {
544 if (global.tune.maxaccept != 0) {
545 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100553 }
554 global.tune.maxaccept = atol(args[1]);
555 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200556 else if (!strcmp(args[0], "tune.chksize")) {
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.chksize = atol(args[1]);
563 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200564#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100565 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566 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.sslcachesize = atol(args[1]);
572 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100573 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
574 unsigned int ssllifetime;
575 const char *res;
576
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582
583 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
584 if (res) {
585 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
586 file, linenum, *res, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590
591 global.tune.ssllifetime = ssllifetime;
592 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100593 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.ssl_max_record = atol(args[1]);
600 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200601#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200602 else if (!strcmp(args[0], "tune.bufsize")) {
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.bufsize = atol(args[1]);
609 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
610 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100611 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200612 }
613 else if (!strcmp(args[0], "tune.maxrewrite")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.maxrewrite = atol(args[1]);
620 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
621 global.tune.maxrewrite = global.tune.bufsize / 2;
622 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100623 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
624 if (global.tune.client_rcvbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_rcvbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
637 if (global.tune.server_rcvbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_rcvbuf = atol(args[1]);
648 }
649 else if (!strcmp(args[0], "tune.sndbuf.client")) {
650 if (global.tune.client_sndbuf != 0) {
651 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT;
653 goto out;
654 }
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.client_sndbuf = atol(args[1]);
661 }
662 else if (!strcmp(args[0], "tune.sndbuf.server")) {
663 if (global.tune.server_sndbuf != 0) {
664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
665 err_code |= ERR_ALERT;
666 goto out;
667 }
668 if (*(args[1]) == 0) {
669 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
670 err_code |= ERR_ALERT | ERR_FATAL;
671 goto out;
672 }
673 global.tune.server_sndbuf = atol(args[1]);
674 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200675 else if (!strcmp(args[0], "tune.pipesize")) {
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681 global.tune.pipesize = atol(args[1]);
682 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100683 else if (!strcmp(args[0], "tune.http.cookielen")) {
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
688 }
689 global.tune.cookie_len = atol(args[1]) + 1;
690 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200691 else if (!strcmp(args[0], "tune.http.maxhdr")) {
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 global.tune.max_http_hdr = atol(args[1]);
698 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100699 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
700#ifdef USE_ZLIB
701 if (*args[1]) {
702 global.tune.zlibmemlevel = atoi(args[1]);
703 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
704 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
705 file, linenum, args[0]);
706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
708 }
709 } else {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715#else
716 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719#endif
720 }
721 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
722#ifdef USE_ZLIB
723 if (*args[1]) {
724 global.tune.zlibwindowsize = atoi(args[1]);
725 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
726 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
727 file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 } else {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737#else
738 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
739 err_code |= ERR_ALERT | ERR_FATAL;
740 goto out;
741#endif
742 }
William Lallemandf3747832012-11-09 12:33:10 +0100743 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
744 if (*args[1]) {
745 global.tune.comp_maxlevel = atoi(args[1]);
746 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
747 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
748 file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 } else {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 else if (!strcmp(args[0], "uid")) {
760 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200761 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT;
763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769 }
770 global.uid = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "gid")) {
773 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200774 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 }
783 global.gid = atol(args[1]);
784 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 /* user/group name handling */
786 else if (!strcmp(args[0], "user")) {
787 struct passwd *ha_user;
788 if (global.uid != 0) {
789 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200792 }
793 errno = 0;
794 ha_user = getpwnam(args[1]);
795 if (ha_user != NULL) {
796 global.uid = (int)ha_user->pw_uid;
797 }
798 else {
799 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 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200801 }
802 }
803 else if (!strcmp(args[0], "group")) {
804 struct group *ha_group;
805 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200806 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200807 err_code |= ERR_ALERT;
808 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200809 }
810 errno = 0;
811 ha_group = getgrnam(args[1]);
812 if (ha_group != NULL) {
813 global.gid = (int)ha_group->gr_gid;
814 }
815 else {
816 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 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200818 }
819 }
820 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200821 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 if (*(args[1]) == 0) {
823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_ALERT | ERR_FATAL;
825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200826 }
827 global.nbproc = atol(args[1]);
828 }
829 else if (!strcmp(args[0], "maxconn")) {
830 if (global.maxconn != 0) {
831 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200832 err_code |= ERR_ALERT;
833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
835 if (*(args[1]) == 0) {
836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200837 err_code |= ERR_ALERT | ERR_FATAL;
838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840 global.maxconn = atol(args[1]);
841#ifdef SYSTEM_MAXCONN
842 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
843 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);
844 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200845 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847#endif /* SYSTEM_MAXCONN */
848 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200849 else if (!strcmp(args[0], "maxsslconn")) {
850#ifdef USE_OPENSSL
851 if (*(args[1]) == 0) {
852 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
853 err_code |= ERR_ALERT | ERR_FATAL;
854 goto out;
855 }
856 global.maxsslconn = atol(args[1]);
857#else
Emeric Brun0914df82012-10-02 18:45:42 +0200858 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200861#endif
862 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200863 else if (!strcmp(args[0], "maxconnrate")) {
864 if (global.cps_lim != 0) {
865 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT;
867 goto out;
868 }
869 if (*(args[1]) == 0) {
870 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874 global.cps_lim = atol(args[1]);
875 }
William Lallemandd85f9172012-11-09 17:05:39 +0100876 else if (!strcmp(args[0], "maxcomprate")) {
877 if (*(args[1]) == 0) {
878 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882 global.comp_rate_lim = atoi(args[1]) * 1024;
883 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100884 else if (!strcmp(args[0], "maxpipes")) {
885 if (global.maxpipes != 0) {
886 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200887 err_code |= ERR_ALERT;
888 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100889 }
890 if (*(args[1]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100894 }
895 global.maxpipes = atol(args[1]);
896 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 else if (!strcmp(args[0], "maxzlibmem")) {
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
William Lallemande3a7d992012-11-20 11:25:20 +0100903 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100904 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100905 else if (!strcmp(args[0], "maxcompcpuusage")) {
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100912 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917}
918
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 else if (!strcmp(args[0], "ulimit-n")) {
920 if (global.rlimit_nofile != 0) {
921 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
925 if (*(args[1]) == 0) {
926 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 global.rlimit_nofile = atol(args[1]);
931 }
932 else if (!strcmp(args[0], "chroot")) {
933 if (global.chroot != NULL) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT;
936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 global.chroot = strdup(args[1]);
944 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200945 else if (!strcmp(args[0], "description")) {
946 int i, len=0;
947 char *d;
948
949 if (!*args[1]) {
950 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
951 file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 for(i=1; *args[i]; i++)
957 len += strlen(args[i])+1;
958
959 if (global.desc)
960 free(global.desc);
961
962 global.desc = d = (char *)calloc(1, len);
963
964 d += sprintf(d, "%s", args[1]);
965 for(i=2; *args[i]; i++)
966 d += sprintf(d, " %s", args[i]);
967 }
968 else if (!strcmp(args[0], "node")) {
969 int i;
970 char c;
971
972 for (i=0; args[1][i]; i++) {
973 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100974 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
975 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200976 break;
977 }
978
979 if (!i || args[1][i]) {
980 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
981 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
982 file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
986
987 if (global.node)
988 free(global.node);
989
990 global.node = strdup(args[1]);
991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 else if (!strcmp(args[0], "pidfile")) {
993 if (global.pidfile != NULL) {
994 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 }
1003 global.pidfile = strdup(args[1]);
1004 }
Emeric Bruned760922010-10-22 17:59:25 +02001005 else if (!strcmp(args[0], "unix-bind")) {
1006 int cur_arg = 1;
1007 while (*(args[cur_arg])) {
1008 if (!strcmp(args[cur_arg], "prefix")) {
1009 if (global.unix_bind.prefix != NULL) {
1010 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT;
1012 cur_arg += 2;
1013 continue;
1014 }
1015
1016 if (*(args[cur_arg+1]) == 0) {
1017 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020 }
1021 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "mode")) {
1027
1028 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "uid")) {
1034
1035 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "gid")) {
1041
1042 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1043 cur_arg += 2;
1044 continue;
1045 }
1046
1047 if (!strcmp(args[cur_arg], "user")) {
1048 struct passwd *user;
1049
1050 user = getpwnam(args[cur_arg + 1]);
1051 if (!user) {
1052 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1053 file, linenum, args[0], args[cur_arg + 1 ]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057
1058 global.unix_bind.ux.uid = user->pw_uid;
1059 cur_arg += 2;
1060 continue;
1061 }
1062
1063 if (!strcmp(args[cur_arg], "group")) {
1064 struct group *group;
1065
1066 group = getgrnam(args[cur_arg + 1]);
1067 if (!group) {
1068 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1069 file, linenum, args[0], args[cur_arg + 1 ]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073
1074 global.unix_bind.ux.gid = group->gr_gid;
1075 cur_arg += 2;
1076 continue;
1077 }
1078
Willy Tarreaub48f9582011-09-05 01:17:06 +02001079 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001080 file, linenum, args[0]);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto out;
1083 }
1084 }
William Lallemand0f99e342011-10-12 17:50:54 +02001085 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1086 /* delete previous herited or defined syslog servers */
1087 struct logsrv *back;
1088 struct logsrv *tmp;
1089
1090 if (*(args[1]) != 0) {
1091 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095
1096 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1097 LIST_DEL(&tmp->list);
1098 free(tmp);
1099 }
1100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001102 struct sockaddr_storage *sk;
1103 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001104 struct logsrv *logsrv;
1105
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 if (*(args[1]) == 0 || *(args[2]) == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111
1112 logsrv = calloc(1, sizeof(struct logsrv));
1113
1114 logsrv->facility = get_log_facility(args[2]);
1115 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120
William Lallemand0f99e342011-10-12 17:50:54 +02001121 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = get_log_level(args[3]);
1124 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 }
1130
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001132 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = get_log_level(args[4]);
1134 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001135 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001138 }
1139 }
1140
Willy Tarreau902636f2013-03-10 19:44:48 +01001141 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001145 free(logsrv);
1146 goto out;
1147 }
1148 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001149
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001150 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151 if (port1 != port2) {
1152 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1153 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 goto out;
1157 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001161 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163
William Lallemand0f99e342011-10-12 17:50:54 +02001164 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001165 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001166 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1167 char *name;
1168 int len;
1169
1170 if (global.log_send_hostname != NULL) {
1171 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT;
1173 goto out;
1174 }
1175
1176 if (*(args[1]))
1177 name = args[1];
1178 else
1179 name = hostname;
1180
1181 len = strlen(name);
1182
1183 /* We'll add a space after the name to respect the log format */
1184 free(global.log_send_hostname);
1185 global.log_send_hostname = malloc(len + 2);
1186 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1187 }
Kevinm48936af2010-12-22 16:08:21 +00001188 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1189 if (*(args[1]) == 0) {
1190 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1191 err_code |= ERR_ALERT | ERR_FATAL;
1192 goto out;
1193 }
1194 free(global.log_tag);
1195 global.log_tag = strdup(args[1]);
1196 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001197 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1198 if (global.spread_checks != 0) {
1199 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001200 err_code |= ERR_ALERT;
1201 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001202 }
1203 if (*(args[1]) == 0) {
1204 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001207 }
1208 global.spread_checks = atol(args[1]);
1209 if (global.spread_checks < 0 || global.spread_checks > 50) {
1210 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001214 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1215#ifdef USE_CPU_AFFINITY
1216 int cur_arg, i;
1217 unsigned int proc = 0;
1218 unsigned long cpus = 0;
1219
1220 if (strcmp(args[1], "all") == 0)
1221 proc = 0xFFFFFFFF;
1222 else if (strcmp(args[1], "odd") == 0)
1223 proc = 0x55555555;
1224 else if (strcmp(args[1], "even") == 0)
1225 proc = 0xAAAAAAAA;
1226 else {
1227 proc = atoi(args[1]);
1228 if (proc >= 1 && proc <= 32)
1229 proc = 1 << (proc - 1);
1230 }
1231
1232 if (!proc || !*args[2]) {
1233 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",
1234 file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238
1239 cur_arg = 2;
1240 while (*args[cur_arg]) {
1241 unsigned int low, high;
1242
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001243 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001244 char *dash = strchr(args[cur_arg], '-');
1245
1246 low = high = str2uic(args[cur_arg]);
1247 if (dash)
1248 high = str2uic(dash + 1);
1249
1250 if (high < low) {
1251 unsigned int swap = low;
1252 low = high;
1253 high = swap;
1254 }
1255
1256 if (low < 0 || high >= sizeof(long) * 8) {
1257 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1258 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 while (low <= high)
1264 cpus |= 1UL << low++;
1265 }
1266 else {
1267 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1268 file, linenum, args[0], args[cur_arg]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272 cur_arg++;
1273 }
1274 for (i = 0; i < 32; i++)
1275 if (proc & (1 << i))
1276 global.cpu_map[i] = cpus;
1277#else
1278 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281#endif
1282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001284 struct cfg_kw_list *kwl;
1285 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001287
1288 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1289 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1290 if (kwl->kw[index].section != CFG_GLOBAL)
1291 continue;
1292 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001293 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001295 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001297 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001298 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001299 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_WARN;
1301 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001304 }
1305 }
1306 }
1307
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001309 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001311
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001313 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315}
1316
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001317void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001319 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320 defproxy.mode = PR_MODE_TCP;
1321 defproxy.state = PR_STNEW;
1322 defproxy.maxconn = cfg_maxpconn;
1323 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001324
Simon Horman66183002013-02-23 10:16:43 +09001325 defproxy.defsrv.check.inter = DEF_CHKINTR;
1326 defproxy.defsrv.check.fastinter = 0;
1327 defproxy.defsrv.check.downinter = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001328 defproxy.defsrv.rise = DEF_RISETIME;
1329 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001330 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001331 defproxy.defsrv.maxqueue = 0;
1332 defproxy.defsrv.minconn = 0;
1333 defproxy.defsrv.maxconn = 0;
1334 defproxy.defsrv.slowstart = 0;
1335 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1336 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1337 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338}
1339
Willy Tarreauade5ec42010-01-28 19:33:49 +01001340
1341static int create_cond_regex_rule(const char *file, int line,
1342 struct proxy *px, int dir, int action, int flags,
1343 const char *cmd, const char *reg, const char *repl,
1344 const char **cond_start)
1345{
1346 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001347 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348 const char *err;
1349 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001350 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001351
1352 if (px == &defproxy) {
1353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto err;
1356 }
1357
1358 if (*reg == 0) {
1359 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1365 err_code |= ERR_WARN;
1366
Willy Tarreau5321c422010-01-28 20:35:13 +01001367 if (cond_start &&
1368 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001369 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1370 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1371 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001372 err_code |= ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375 }
1376 else if (cond_start && **cond_start) {
1377 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1378 file, line, cmd, *cond_start);
1379 err_code |= ERR_ALERT | ERR_FATAL;
1380 goto err;
1381 }
1382
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001383 err_code |= warnif_cond_conflicts(cond,
1384 (dir == SMP_OPT_DIR_REQ) ?
1385 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1386 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1387 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388
Willy Tarreauade5ec42010-01-28 19:33:49 +01001389 preg = calloc(1, sizeof(regex_t));
1390 if (!preg) {
1391 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1392 err_code = ERR_ALERT | ERR_FATAL;
1393 goto err;
1394 }
1395
1396 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1397 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1398 err_code = ERR_ALERT | ERR_FATAL;
1399 goto err;
1400 }
1401
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001402 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001403 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 if (repl && err) {
1405 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1406 file, line, cmd, *err);
1407 err_code |= ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001411 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 err_code |= ERR_WARN;
1413
Willy Tarreauf4068b62012-05-08 17:37:49 +02001414 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001415 return err_code;
1416 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001417 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001418 free(preg);
1419 return err_code;
1420}
1421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001424 * Returns the error code, 0 if OK, or any combination of :
1425 * - ERR_ABORT: must abort ASAP
1426 * - ERR_FATAL: we can continue parsing but not start the service
1427 * - ERR_WARN: a warning has been emitted
1428 * - ERR_ALERT: an alert has been emitted
1429 * Only the two first ones can stop processing, the two others are just
1430 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001432int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1433{
1434 static struct peers *curpeers = NULL;
1435 struct peer *newpeer = NULL;
1436 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001437 struct bind_conf *bind_conf;
1438 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001440 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001443 if (!*args[1]) {
1444 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 err = invalid_char(args[1]);
1450 if (err) {
1451 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1452 file, linenum, *err, args[0], args[1]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001454 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001485 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau902636f2013-03-10 19:44:48 +01001519 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001520 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001525
1526 proto = protocol_by_family(sk->ss_family);
1527 if (!proto || !proto->connect) {
1528 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1529 file, linenum, args[0], args[1]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533
1534 if (port1 != port2) {
1535 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1536 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001537 err_code |= ERR_ALERT | ERR_FATAL;
1538 goto out;
1539 }
1540
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541 if (!port1) {
1542 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1543 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001549 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001550 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001551 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001552
Emeric Brun32da3c42010-09-23 18:39:19 +02001553 if (strcmp(newpeer->id, localpeer) == 0) {
1554 /* Current is local peer, it define a frontend */
1555 newpeer->local = 1;
1556
1557 if (!curpeers->peers_fe) {
1558 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1559 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1560 err_code |= ERR_ALERT | ERR_ABORT;
1561 goto out;
1562 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001563
Willy Tarreau237250c2011-07-29 01:49:03 +02001564 init_new_proxy(curpeers->peers_fe);
1565 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001566
1567 curpeers->peers_fe->last_change = now.tv_sec;
1568 curpeers->peers_fe->id = strdup(args[1]);
1569 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001570 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1572 curpeers->peers_fe->timeout.connect = 5000;
1573 curpeers->peers_fe->accept = peer_accept;
1574 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001575 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1576 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1579
Willy Tarreau902636f2013-03-10 19:44:48 +01001580 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1581 if (errmsg && *errmsg) {
1582 indent_msg(&errmsg, 2);
1583 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001584 }
1585 else
1586 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1587 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001619 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001620 return err_code;
1621}
1622
1623
Willy Tarreau3842f002009-06-14 11:39:52 +02001624int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625{
1626 static struct proxy *curproxy = NULL;
1627 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001628 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001629 int rc;
1630 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001631 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001632 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001633 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001634 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001635 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637 if (!strcmp(args[0], "listen"))
1638 rc = PR_CAP_LISTEN;
1639 else if (!strcmp(args[0], "frontend"))
1640 rc = PR_CAP_FE | PR_CAP_RS;
1641 else if (!strcmp(args[0], "backend"))
1642 rc = PR_CAP_BE | PR_CAP_RS;
1643 else if (!strcmp(args[0], "ruleset"))
1644 rc = PR_CAP_RS;
1645 else
1646 rc = PR_CAP_NONE;
1647
1648 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (!*args[1]) {
1650 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1651 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_ABORT;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001656
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001657 err = invalid_char(args[1]);
1658 if (err) {
1659 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1660 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001661 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001662 }
1663
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1665 /*
1666 * If there are two proxies with the same name only following
1667 * combinations are allowed:
1668 *
1669 * listen backend frontend ruleset
1670 * listen - - - -
1671 * backend - - OK -
1672 * frontend - OK - -
1673 * ruleset - - - -
1674 */
1675
1676 if (!strcmp(curproxy->id, args[1]) &&
1677 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1678 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001679 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1680 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1681 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001683 }
1684 }
1685
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1687 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_ABORT;
1689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001691
Willy Tarreau97cb7802010-01-03 20:23:58 +01001692 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693 curproxy->next = proxy;
1694 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001695 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1696 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001697 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
1701 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau902636f2013-03-10 19:44:48 +01001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1708 if (errmsg && *errmsg) {
1709 indent_msg(&errmsg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_FATAL;
1716 goto out;
1717 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001720 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 }
1723
1724 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001725 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001726 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001727
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001730 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001731 curproxy->no_options = defproxy.no_options;
1732 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001733 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001734 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001735 curproxy->except_net = defproxy.except_net;
1736 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001737 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001738 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001740 if (defproxy.fwdfor_hdr_len) {
1741 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1742 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1743 }
1744
Willy Tarreaub86db342009-11-30 11:50:16 +01001745 if (defproxy.orgto_hdr_len) {
1746 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1747 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1748 }
1749
Mark Lamourinec2247f02012-01-04 13:02:01 -05001750 if (defproxy.server_id_hdr_len) {
1751 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1752 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1753 }
1754
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 if (curproxy->cap & PR_CAP_FE) {
1756 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001757 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001758 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001759
1760 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1762 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763
1764 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (curproxy->cap & PR_CAP_BE) {
1768 curproxy->fullconn = defproxy.fullconn;
1769 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001771 if (defproxy.check_req) {
1772 curproxy->check_req = calloc(1, defproxy.check_len);
1773 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1774 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001777 if (defproxy.expect_str) {
1778 curproxy->expect_str = strdup(defproxy.expect_str);
1779 if (defproxy.expect_regex) {
1780 /* note: this regex is known to be valid */
1781 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1782 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1783 }
1784 }
1785
Willy Tarreau67402132012-05-31 20:40:20 +02001786 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (defproxy.cookie_name)
1788 curproxy->cookie_name = strdup(defproxy.cookie_name);
1789 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001790 if (defproxy.cookie_domain)
1791 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001792
Willy Tarreau31936852010-10-06 16:59:56 +02001793 if (defproxy.cookie_maxidle)
1794 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1795
1796 if (defproxy.cookie_maxlife)
1797 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1798
Emeric Brun647caf12009-06-30 17:57:00 +02001799 if (defproxy.rdp_cookie_name)
1800 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1801 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1802
Willy Tarreau01732802007-11-01 22:48:15 +01001803 if (defproxy.url_param_name)
1804 curproxy->url_param_name = strdup(defproxy.url_param_name);
1805 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001806
Benoitaffb4812009-03-25 13:02:10 +01001807 if (defproxy.hh_name)
1808 curproxy->hh_name = strdup(defproxy.hh_name);
1809 curproxy->hh_len = defproxy.hh_len;
1810 curproxy->hh_match_domain = defproxy.hh_match_domain;
1811
Willy Tarreauef9a3602012-12-08 22:29:20 +01001812 if (defproxy.conn_src.iface_name)
1813 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1814 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001815 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001816#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001817 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001818#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001820
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001821 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001822 if (defproxy.capture_name)
1823 curproxy->capture_name = strdup(defproxy.capture_name);
1824 curproxy->capture_namelen = defproxy.capture_namelen;
1825 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001829 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001830 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001831 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001832 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 curproxy->uri_auth = defproxy.uri_auth;
1834 curproxy->mon_net = defproxy.mon_net;
1835 curproxy->mon_mask = defproxy.mon_mask;
1836 if (defproxy.monitor_uri)
1837 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1838 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001839 if (defproxy.defbe.name)
1840 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001841
1842 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001843 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1844 if (curproxy->conf.logformat_string &&
1845 curproxy->conf.logformat_string != default_http_log_format &&
1846 curproxy->conf.logformat_string != default_tcp_log_format &&
1847 curproxy->conf.logformat_string != clf_http_log_format)
1848 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1849
1850 if (defproxy.conf.lfs_file) {
1851 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1852 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1853 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 }
1855
1856 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001857 curproxy->timeout.connect = defproxy.timeout.connect;
1858 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001859 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001860 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001861 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001862 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001863 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001864 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001865 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 }
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001869
1870 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001871 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001872 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001873 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001874 LIST_INIT(&node->list);
1875 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1876 }
1877
Willy Tarreau62a61232013-04-12 18:13:46 +02001878 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1879 if (curproxy->conf.uniqueid_format_string)
1880 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1881
1882 if (defproxy.conf.uif_file) {
1883 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1884 curproxy->conf.uif_line = defproxy.conf.uif_line;
1885 }
William Lallemanda73203e2012-03-12 12:48:57 +01001886
1887 /* copy default header unique id */
1888 if (defproxy.header_unique_id)
1889 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1890
William Lallemand82fe75c2012-10-23 10:25:10 +02001891 /* default compression options */
1892 if (defproxy.comp != NULL) {
1893 curproxy->comp = calloc(1, sizeof(struct comp));
1894 curproxy->comp->algos = defproxy.comp->algos;
1895 curproxy->comp->types = defproxy.comp->types;
1896 }
1897
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001899 curproxy->conf.used_listener_id = EB_ROOT;
1900 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901
Willy Tarreau93893792009-07-23 13:19:11 +02001902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 }
1904 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1905 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001906 /* FIXME-20070101: we should do this too at the end of the
1907 * config parsing to free all default values.
1908 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001909 free(defproxy.check_req);
1910 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001911 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001912 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001913 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001914 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001915 free(defproxy.capture_name);
1916 free(defproxy.monitor_uri);
1917 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001918 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001919 free(defproxy.fwdfor_hdr_name);
1920 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001921 free(defproxy.orgto_hdr_name);
1922 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001923 free(defproxy.server_id_hdr_name);
1924 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001925 free(defproxy.expect_str);
1926 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001927
Willy Tarreau62a61232013-04-12 18:13:46 +02001928 if (defproxy.conf.logformat_string != default_http_log_format &&
1929 defproxy.conf.logformat_string != default_tcp_log_format &&
1930 defproxy.conf.logformat_string != clf_http_log_format)
1931 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001932
Willy Tarreau62a61232013-04-12 18:13:46 +02001933 free(defproxy.conf.uniqueid_format_string);
1934 free(defproxy.conf.lfs_file);
1935 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001938 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 /* we cannot free uri_auth because it might already be used */
1941 init_default_instance();
1942 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001943 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1944 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001945 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001947 }
1948 else if (curproxy == NULL) {
1949 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001953
1954 /* update the current file and line being parsed */
1955 curproxy->conf.args.file = curproxy->conf.file;
1956 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957
1958 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001960 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001961 int cur_arg;
1962
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 if (curproxy == &defproxy) {
1964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970
Willy Tarreau24709282013-03-10 21:32:12 +01001971 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001972 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001977
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001978 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001979
1980 /* use default settings for unix sockets */
1981 bind_conf->ux.uid = global.unix_bind.ux.uid;
1982 bind_conf->ux.gid = global.unix_bind.ux.gid;
1983 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001984
1985 /* NOTE: the following line might create several listeners if there
1986 * are comma-separated IPs or port ranges. So all further processing
1987 * will have to be applied to all listeners created after last_listen.
1988 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001989 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1990 if (errmsg && *errmsg) {
1991 indent_msg(&errmsg, 2);
1992 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001993 }
1994 else
1995 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1996 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002000
Willy Tarreau4348fad2012-09-20 16:48:07 +02002001 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2002 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002003 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002004 }
2005
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002006 cur_arg = 2;
2007 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002008 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002009 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002010 char *err;
2011
Willy Tarreau26982662012-09-12 23:17:10 +02002012 kw = bind_find_kw(args[cur_arg]);
2013 if (kw) {
2014 char *err = NULL;
2015 int code;
2016
2017 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002018 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2019 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002020 cur_arg += 1 + kw->skip ;
2021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
2023 }
2024
Willy Tarreau4348fad2012-09-20 16:48:07 +02002025 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002026 err_code |= code;
2027
2028 if (code) {
2029 if (err && *err) {
2030 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002031 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002032 }
2033 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002034 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2035 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002036 if (code & ERR_FATAL) {
2037 free(err);
2038 cur_arg += 1 + kw->skip;
2039 goto out;
2040 }
2041 }
2042 free(err);
2043 cur_arg += 1 + kw->skip;
2044 continue;
2045 }
2046
Willy Tarreau8638f482012-09-18 18:01:17 +02002047 err = NULL;
2048 if (!bind_dumped) {
2049 bind_dump_kws(&err);
2050 indent_msg(&err, 4);
2051 bind_dumped = 1;
2052 }
2053
2054 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2055 file, linenum, args[0], args[1], args[cur_arg],
2056 err ? " Registered keywords :" : "", err ? err : "");
2057 free(err);
2058
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002061 }
Willy Tarreau93893792009-07-23 13:19:11 +02002062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
2064 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2065 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2066 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 /* flush useless bits */
2075 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002078 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081
Willy Tarreau1c47f852006-07-09 08:22:27 +02002082 if (!*args[1]) {
2083 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002087 }
2088
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002090 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002091 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002092 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2094
Willy Tarreau93893792009-07-23 13:19:11 +02002095 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002096 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2098 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2099 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2100 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2101 else {
2102 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
2106 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002107 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002108 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109
2110 if (curproxy == &defproxy) {
2111 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002115 }
2116
2117 if (!*args[1]) {
2118 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002120 err_code |= ERR_ALERT | ERR_FATAL;
2121 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002122 }
2123
2124 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002125 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002126
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002127 if (curproxy->uuid <= 0) {
2128 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002132 }
2133
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002134 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2135 if (node) {
2136 struct proxy *target = container_of(node, struct proxy, conf.id);
2137 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2138 file, linenum, proxy_type_str(curproxy), curproxy->id,
2139 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
2142 }
2143 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002145 else if (!strcmp(args[0], "description")) {
2146 int i, len=0;
2147 char *d;
2148
Cyril Bonté99ed3272010-01-24 23:29:44 +01002149 if (curproxy == &defproxy) {
2150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2151 file, linenum, args[0]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002156 if (!*args[1]) {
2157 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2158 file, linenum, args[0]);
2159 return -1;
2160 }
2161
2162 for(i=1; *args[i]; i++)
2163 len += strlen(args[i])+1;
2164
2165 d = (char *)calloc(1, len);
2166 curproxy->desc = d;
2167
2168 d += sprintf(d, "%s", args[1]);
2169 for(i=2; *args[i]; i++)
2170 d += sprintf(d, " %s", args[i]);
2171
2172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002173 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2174 curproxy->state = PR_STSTOPPED;
2175 }
2176 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2177 curproxy->state = PR_STNEW;
2178 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002179 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2180 int cur_arg = 1;
2181 unsigned int set = 0;
2182
2183 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002184 unsigned int low, high;
2185
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002186 if (strcmp(args[cur_arg], "all") == 0) {
2187 set = 0;
2188 break;
2189 }
2190 else if (strcmp(args[cur_arg], "odd") == 0) {
2191 set |= 0x55555555;
2192 }
2193 else if (strcmp(args[cur_arg], "even") == 0) {
2194 set |= 0xAAAAAAAA;
2195 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002196 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002197 char *dash = strchr(args[cur_arg], '-');
2198
2199 low = high = str2uic(args[cur_arg]);
2200 if (dash)
2201 high = str2uic(dash + 1);
2202
2203 if (high < low) {
2204 unsigned int swap = low;
2205 low = high;
2206 high = swap;
2207 }
2208
2209 if (low < 1 || high > 32) {
2210 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002211 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002214 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002215
2216 if (high > global.nbproc) {
2217 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2218 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002220 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002221 while (low <= high)
2222 set |= 1 << (low++ - 1);
2223 }
2224 else {
2225 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2226 file, linenum, args[0]);
2227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002229 }
2230 cur_arg++;
2231 }
2232 curproxy->bind_proc = set;
2233 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002234 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002235 if (curproxy == &defproxy) {
2236 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002239 }
2240
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002241 err = invalid_char(args[1]);
2242 if (err) {
2243 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2244 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002246 }
2247
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002248 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002249 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2250 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002253 }
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2256 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257
Willy Tarreau977b8e42006-12-29 14:19:17 +01002258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (*(args[1]) == 0) {
2262 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002267
Willy Tarreau67402132012-05-31 20:40:20 +02002268 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002269 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002270 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002271 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 curproxy->cookie_name = strdup(args[1]);
2273 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 cur_arg = 2;
2276 while (*(args[cur_arg])) {
2277 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002284 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002287 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002290 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002292 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002293 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002296 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002298 else if (!strcmp(args[cur_arg], "httponly")) {
2299 curproxy->ck_opts |= PR_CK_HTTPONLY;
2300 }
2301 else if (!strcmp(args[cur_arg], "secure")) {
2302 curproxy->ck_opts |= PR_CK_SECURE;
2303 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002304 else if (!strcmp(args[cur_arg], "domain")) {
2305 if (!*args[cur_arg + 1]) {
2306 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2307 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 }
2311
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002312 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002313 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002314 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2315 " dots nor does not start with a dot."
2316 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002317 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002318 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002319 }
2320
2321 err = invalid_domainchar(args[cur_arg + 1]);
2322 if (err) {
2323 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2324 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002327 }
2328
Willy Tarreau68a897b2009-12-03 23:28:34 +01002329 if (!curproxy->cookie_domain) {
2330 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2331 } else {
2332 /* one domain was already specified, add another one by
2333 * building the string which will be returned along with
2334 * the cookie.
2335 */
2336 char *new_ptr;
2337 int new_len = strlen(curproxy->cookie_domain) +
2338 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2339 new_ptr = malloc(new_len);
2340 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2341 free(curproxy->cookie_domain);
2342 curproxy->cookie_domain = new_ptr;
2343 }
Willy Tarreau31936852010-10-06 16:59:56 +02002344 cur_arg++;
2345 }
2346 else if (!strcmp(args[cur_arg], "maxidle")) {
2347 unsigned int maxidle;
2348 const char *res;
2349
2350 if (!*args[cur_arg + 1]) {
2351 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2352 file, linenum, args[cur_arg]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
2357 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2358 if (res) {
2359 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2360 file, linenum, *res, args[cur_arg]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 curproxy->cookie_maxidle = maxidle;
2365 cur_arg++;
2366 }
2367 else if (!strcmp(args[cur_arg], "maxlife")) {
2368 unsigned int maxlife;
2369 const char *res;
2370
2371 if (!*args[cur_arg + 1]) {
2372 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2373 file, linenum, args[cur_arg]);
2374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
2376 }
2377
2378 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2379 if (res) {
2380 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2381 file, linenum, *res, args[cur_arg]);
2382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
2384 }
2385 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002386 cur_arg++;
2387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002389 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 +02002390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 cur_arg++;
2395 }
Willy Tarreau67402132012-05-31 20:40:20 +02002396 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2398 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
Willy Tarreau67402132012-05-31 20:40:20 +02002402 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002407
Willy Tarreau67402132012-05-31 20:40:20 +02002408 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002409 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2410 file, linenum);
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002414 else if (!strcmp(args[0], "persist")) { /* persist */
2415 if (*(args[1]) == 0) {
2416 Alert("parsing [%s:%d] : missing persist method.\n",
2417 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002420 }
2421
2422 if (!strncmp(args[1], "rdp-cookie", 10)) {
2423 curproxy->options2 |= PR_O2_RDPC_PRST;
2424
Emeric Brunb982a3d2010-01-04 15:45:53 +01002425 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002426 const char *beg, *end;
2427
2428 beg = args[1] + 11;
2429 end = strchr(beg, ')');
2430
2431 if (!end || end == beg) {
2432 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2433 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002436 }
2437
2438 free(curproxy->rdp_cookie_name);
2439 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2440 curproxy->rdp_cookie_len = end-beg;
2441 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002442 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002443 free(curproxy->rdp_cookie_name);
2444 curproxy->rdp_cookie_name = strdup("msts");
2445 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2446 }
2447 else { /* syntax */
2448 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2449 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002452 }
2453 }
2454 else {
2455 Alert("parsing [%s:%d] : unknown persist method.\n",
2456 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002459 }
2460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002462 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002464 if (curproxy == &defproxy) {
2465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469
Willy Tarreau977b8e42006-12-29 14:19:17 +01002470 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002472
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002474 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002480 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 curproxy->appsession_name = strdup(args[1]);
2482 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2483 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002484 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2485 if (err) {
2486 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2487 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002490 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002491 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002492
Willy Tarreau51041c72007-09-09 21:56:53 +02002493 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2494 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_ABORT;
2496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498
2499 cur_arg = 6;
2500 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2502 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002503 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002504 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002505 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002506 } else if (!strcmp(args[cur_arg], "prefix")) {
2507 curproxy->options2 |= PR_O2_AS_PFX;
2508 } else if (!strcmp(args[cur_arg], "mode")) {
2509 if (!*args[cur_arg + 1]) {
2510 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2511 file, linenum, args[0], args[cur_arg]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515
2516 cur_arg++;
2517 if (!strcmp(args[cur_arg], "query-string")) {
2518 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2519 curproxy->options2 |= PR_O2_AS_M_QS;
2520 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2521 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2522 curproxy->options2 |= PR_O2_AS_M_PP;
2523 } else {
2524 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
2527 }
2528 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002529 cur_arg++;
2530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 } /* Url App Session */
2532 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002533 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002535
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002537 if (curproxy == &defproxy) {
2538 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 if (*(args[4]) == 0) {
2544 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2545 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002549 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->capture_name = strdup(args[2]);
2551 curproxy->capture_namelen = strlen(curproxy->capture_name);
2552 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 curproxy->to_log |= LW_COOKIE;
2554 }
2555 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2556 struct cap_hdr *hdr;
2557
2558 if (curproxy == &defproxy) {
2559 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 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 }
2563
2564 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2565 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2566 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 }
2570
2571 hdr = calloc(sizeof(struct cap_hdr), 1);
2572 hdr->next = curproxy->req_cap;
2573 hdr->name = strdup(args[3]);
2574 hdr->namelen = strlen(args[3]);
2575 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002576 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 hdr->index = curproxy->nb_req_cap++;
2578 curproxy->req_cap = hdr;
2579 curproxy->to_log |= LW_REQHDR;
2580 }
2581 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2582 struct cap_hdr *hdr;
2583
2584 if (curproxy == &defproxy) {
2585 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 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589
2590 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2591 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2592 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 hdr = calloc(sizeof(struct cap_hdr), 1);
2597 hdr->next = curproxy->rsp_cap;
2598 hdr->name = strdup(args[3]);
2599 hdr->namelen = strlen(args[3]);
2600 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002601 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 hdr->index = curproxy->nb_rsp_cap++;
2603 curproxy->rsp_cap = hdr;
2604 curproxy->to_log |= LW_RSPHDR;
2605 }
2606 else {
2607 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 }
2612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[1]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
2623 curproxy->conn_retries = atol(args[1]);
2624 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002625 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002626 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002627
2628 if (curproxy == &defproxy) {
2629 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633
Willy Tarreau20b0de52012-12-24 15:45:22 +01002634 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2635 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2636 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2637 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002638 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002639 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2640 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 +01002641 file, linenum, args[0]);
2642 err_code |= ERR_WARN;
2643 }
2644
Willy Tarreauff011f22011-01-06 17:51:27 +01002645 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002646
Willy Tarreauff011f22011-01-06 17:51:27 +01002647 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002648 err_code |= ERR_ALERT | ERR_ABORT;
2649 goto out;
2650 }
2651
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002652 err_code |= warnif_cond_conflicts(rule->cond,
2653 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2654 file, linenum);
2655
Willy Tarreauff011f22011-01-06 17:51:27 +01002656 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002657 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002658 else if (!strcmp(args[0], "http-response")) { /* response access control */
2659 struct http_res_rule *rule;
2660
2661 if (curproxy == &defproxy) {
2662 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2668 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2669 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2670 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2671 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2672 file, linenum, args[0]);
2673 err_code |= ERR_WARN;
2674 }
2675
2676 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2677
2678 if (!rule) {
2679 err_code |= ERR_ALERT | ERR_ABORT;
2680 goto out;
2681 }
2682
2683 err_code |= warnif_cond_conflicts(rule->cond,
2684 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2685 file, linenum);
2686
2687 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2688 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002689 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2690 /* set the header name and length into the proxy structure */
2691 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2692 err_code |= ERR_WARN;
2693
2694 if (!*args[1]) {
2695 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2696 file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
2701 /* set the desired header name */
2702 free(curproxy->server_id_hdr_name);
2703 curproxy->server_id_hdr_name = strdup(args[1]);
2704 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2705 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002706 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002707 if (curproxy == &defproxy) {
2708 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002711 }
2712
Willy Tarreauef6494c2010-01-28 17:12:36 +01002713 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002714 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002718 }
2719
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002720 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2721 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2722 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002725 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002726
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002727 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002728 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002729 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002730 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002731 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002732
Cyril Bonté99ed3272010-01-24 23:29:44 +01002733 if (curproxy == &defproxy) {
2734 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738
Willy Tarreau4baae242012-12-27 12:00:31 +01002739 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2740 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2741 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002744 }
2745
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002746 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002747 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002748 err_code |= warnif_cond_conflicts(rule->cond,
2749 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2750 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002751 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002752 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002753 struct switching_rule *rule;
2754
Willy Tarreaub099aca2008-10-12 17:26:37 +02002755 if (curproxy == &defproxy) {
2756 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002759 }
2760
Willy Tarreau55ea7572007-06-17 19:56:27 +02002761 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002762 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002763
2764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002768 }
2769
Willy Tarreauef6494c2010-01-28 17:12:36 +01002770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002771 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002775 }
2776
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002777 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2778 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2779 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002782 }
2783
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002784 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002785
Willy Tarreau55ea7572007-06-17 19:56:27 +02002786 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2787 rule->cond = cond;
2788 rule->be.name = strdup(args[1]);
2789 LIST_INIT(&rule->list);
2790 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2791 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002792 else if (strcmp(args[0], "use-server") == 0) {
2793 struct server_rule *rule;
2794
2795 if (curproxy == &defproxy) {
2796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
2801 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2802 err_code |= ERR_WARN;
2803
2804 if (*(args[1]) == 0) {
2805 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
2809
2810 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2811 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2812 file, linenum, args[0]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002817 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2818 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2819 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002824 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002825
2826 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2827 rule->cond = cond;
2828 rule->srv.name = strdup(args[1]);
2829 LIST_INIT(&rule->list);
2830 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2831 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2832 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002833 else if ((!strcmp(args[0], "force-persist")) ||
2834 (!strcmp(args[0], "ignore-persist"))) {
2835 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002836
2837 if (curproxy == &defproxy) {
2838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842
2843 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2844 err_code |= ERR_WARN;
2845
Willy Tarreauef6494c2010-01-28 17:12:36 +01002846 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002847 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2848 file, linenum, args[0]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002853 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2854 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2855 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002860 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2861 * where force-persist is applied.
2862 */
2863 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002864
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002865 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002866 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002867 if (!strcmp(args[0], "force-persist")) {
2868 rule->type = PERSIST_TYPE_FORCE;
2869 } else {
2870 rule->type = PERSIST_TYPE_IGNORE;
2871 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002872 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002873 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002874 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002875 else if (!strcmp(args[0], "stick-table")) {
2876 int myidx = 1;
2877
Emeric Brun32da3c42010-09-23 18:39:19 +02002878 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 curproxy->table.type = (unsigned int)-1;
2880 while (*args[myidx]) {
2881 const char *err;
2882
2883 if (strcmp(args[myidx], "size") == 0) {
2884 myidx++;
2885 if (!*(args[myidx])) {
2886 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2887 file, linenum, args[myidx-1]);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2892 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2893 file, linenum, *err, args[myidx-1]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002897 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002899 else if (strcmp(args[myidx], "peers") == 0) {
2900 myidx++;
2901 if (!*(args[myidx])) {
2902 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2903 file, linenum, args[myidx-1]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907 curproxy->table.peers.name = strdup(args[myidx++]);
2908 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 else if (strcmp(args[myidx], "expire") == 0) {
2910 myidx++;
2911 if (!*(args[myidx])) {
2912 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2913 file, linenum, args[myidx-1]);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
2917 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2918 if (err) {
2919 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2920 file, linenum, *err, args[myidx-1]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002925 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 }
2927 else if (strcmp(args[myidx], "nopurge") == 0) {
2928 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002929 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 }
2931 else if (strcmp(args[myidx], "type") == 0) {
2932 myidx++;
2933 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2934 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2935 file, linenum, args[myidx]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002939 /* myidx already points to next arg */
2940 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002941 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002942 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002943 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002944
2945 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002946 nw = args[myidx];
2947 while (*nw) {
2948 /* the "store" keyword supports a comma-separated list */
2949 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002950 sa = NULL; /* store arg */
2951 while (*nw && *nw != ',') {
2952 if (*nw == '(') {
2953 *nw = 0;
2954 sa = ++nw;
2955 while (*nw != ')') {
2956 if (!*nw) {
2957 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2958 file, linenum, args[0], cw);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962 nw++;
2963 }
2964 *nw = '\0';
2965 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002966 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002967 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002968 if (*nw)
2969 *nw++ = '\0';
2970 type = stktable_get_data_type(cw);
2971 if (type < 0) {
2972 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2973 file, linenum, args[0], cw);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
Willy Tarreauac782882010-06-20 10:41:54 +02002977
2978 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2979 switch (err) {
2980 case PE_NONE: break;
2981 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002982 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2983 file, linenum, args[0], cw);
2984 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002985 break;
2986
2987 case PE_ARG_MISSING:
2988 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2989 file, linenum, args[0], cw);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992
2993 case PE_ARG_NOT_USED:
2994 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2995 file, linenum, args[0], cw);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998
2999 default:
3000 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3001 file, linenum, args[0], cw);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003004 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003005 }
3006 myidx++;
3007 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003008 else {
3009 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3010 file, linenum, args[myidx]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003013 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 }
3015
3016 if (!curproxy->table.size) {
3017 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3018 file, linenum);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022
3023 if (curproxy->table.type == (unsigned int)-1) {
3024 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3025 file, linenum);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029 }
3030 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003032 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 int myidx = 0;
3034 const char *name = NULL;
3035 int flags;
3036
3037 if (curproxy == &defproxy) {
3038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
3041 }
3042
3043 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3044 err_code |= ERR_WARN;
3045 goto out;
3046 }
3047
3048 myidx++;
3049 if ((strcmp(args[myidx], "store") == 0) ||
3050 (strcmp(args[myidx], "store-request") == 0)) {
3051 myidx++;
3052 flags = STK_IS_STORE;
3053 }
3054 else if (strcmp(args[myidx], "store-response") == 0) {
3055 myidx++;
3056 flags = STK_IS_STORE | STK_ON_RSP;
3057 }
3058 else if (strcmp(args[myidx], "match") == 0) {
3059 myidx++;
3060 flags = STK_IS_MATCH;
3061 }
3062 else if (strcmp(args[myidx], "on") == 0) {
3063 myidx++;
3064 flags = STK_IS_MATCH | STK_IS_STORE;
3065 }
3066 else {
3067 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
3070 }
3071
3072 if (*(args[myidx]) == 0) {
3073 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003078 curproxy->conf.args.ctx = ARGC_STK;
3079 expr = sample_parse_expr(args, &myidx, trash.str, trash.size, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003081 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085
3086 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003087 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3088 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3089 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003090 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003091 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003092 goto out;
3093 }
3094 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003095 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3096 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3097 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003098 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003099 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003100 goto out;
3101 }
3102 }
3103
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003104 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003105 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003106
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 if (strcmp(args[myidx], "table") == 0) {
3108 myidx++;
3109 name = args[myidx++];
3110 }
3111
Willy Tarreauef6494c2010-01-28 17:12:36 +01003112 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003113 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3114 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3115 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003117 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003118 goto out;
3119 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003120 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003121 else if (*(args[myidx])) {
3122 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3123 file, linenum, args[0], args[myidx]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003125 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003126 goto out;
3127 }
Emeric Brun97679e72010-09-23 17:56:44 +02003128 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003129 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003130 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003131 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003132
Emeric Brunb982a3d2010-01-04 15:45:53 +01003133 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3134 rule->cond = cond;
3135 rule->expr = expr;
3136 rule->flags = flags;
3137 rule->table.name = name ? strdup(name) : NULL;
3138 LIST_INIT(&rule->list);
3139 if (flags & STK_ON_RSP)
3140 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3141 else
3142 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003147
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3149 curproxy->uri_auth = NULL; /* we must detach from the default config */
3150
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003151 if (!*args[1]) {
3152 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003153 } else if (!strcmp(args[1], "admin")) {
3154 struct stats_admin_rule *rule;
3155
3156 if (curproxy == &defproxy) {
3157 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
3160 }
3161
3162 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3163 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
3166 }
3167
3168 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3169 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3170 file, linenum, args[0], args[1]);
3171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
3173 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003174 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3175 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3176 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
3180
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003181 err_code |= warnif_cond_conflicts(cond,
3182 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3183 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003184
3185 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3186 rule->cond = cond;
3187 LIST_INIT(&rule->list);
3188 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 } else if (!strcmp(args[1], "uri")) {
3190 if (*(args[2]) == 0) {
3191 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3195 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
3199 } else if (!strcmp(args[1], "realm")) {
3200 if (*(args[2]) == 0) {
3201 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003204 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003209 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003210 unsigned interval;
3211
3212 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3213 if (err) {
3214 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3215 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003218 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3219 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_ABORT;
3221 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003222 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003223 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003224 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003225
3226 if (curproxy == &defproxy) {
3227 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
3231
3232 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3233 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3234 err_code |= ERR_ALERT | ERR_ABORT;
3235 goto out;
3236 }
3237
Willy Tarreauff011f22011-01-06 17:51:27 +01003238 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3239 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003240 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3241 file, linenum, args[0]);
3242 err_code |= ERR_WARN;
3243 }
3244
Willy Tarreauff011f22011-01-06 17:51:27 +01003245 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003246
Willy Tarreauff011f22011-01-06 17:51:27 +01003247 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
3250 }
3251
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003252 err_code |= warnif_cond_conflicts(rule->cond,
3253 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3254 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003255 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003256
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 } else if (!strcmp(args[1], "auth")) {
3258 if (*(args[2]) == 0) {
3259 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3263 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
3267 } else if (!strcmp(args[1], "scope")) {
3268 if (*(args[2]) == 0) {
3269 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_ABORT;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 } else if (!strcmp(args[1], "enable")) {
3278 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_ABORT;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003283 } else if (!strcmp(args[1], "hide-version")) {
3284 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_ABORT;
3287 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003288 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003289 } else if (!strcmp(args[1], "show-legends")) {
3290 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003295 } else if (!strcmp(args[1], "show-node")) {
3296
3297 if (*args[2]) {
3298 int i;
3299 char c;
3300
3301 for (i=0; args[2][i]; i++) {
3302 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003303 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3304 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003305 break;
3306 }
3307
3308 if (!i || args[2][i]) {
3309 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3310 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3311 file, linenum, args[0], args[1]);
3312 err_code |= ERR_ALERT | ERR_FATAL;
3313 goto out;
3314 }
3315 }
3316
3317 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3318 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3319 err_code |= ERR_ALERT | ERR_ABORT;
3320 goto out;
3321 }
3322 } else if (!strcmp(args[1], "show-desc")) {
3323 char *desc = NULL;
3324
3325 if (*args[2]) {
3326 int i, len=0;
3327 char *d;
3328
3329 for(i=2; *args[i]; i++)
3330 len += strlen(args[i])+1;
3331
3332 desc = d = (char *)calloc(1, len);
3333
3334 d += sprintf(d, "%s", args[2]);
3335 for(i=3; *args[i]; i++)
3336 d += sprintf(d, " %s", args[i]);
3337 }
3338
3339 if (!*args[2] && !global.desc)
3340 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3341 file, linenum, args[1]);
3342 else {
3343 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3344 free(desc);
3345 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3346 err_code |= ERR_ALERT | ERR_ABORT;
3347 goto out;
3348 }
3349 free(desc);
3350 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003352stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003353 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 +01003354 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003355 err_code |= ERR_ALERT | ERR_FATAL;
3356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
3358 }
3359 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003360 int optnum;
3361
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003362 if (*(args[1]) == '\0') {
3363 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003368
3369 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3370 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003371 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3372 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3373 file, linenum, cfg_opts[optnum].name);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
Willy Tarreau93893792009-07-23 13:19:11 +02003377 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3378 err_code |= ERR_WARN;
3379 goto out;
3380 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003381
Willy Tarreau3842f002009-06-14 11:39:52 +02003382 curproxy->no_options &= ~cfg_opts[optnum].val;
3383 curproxy->options &= ~cfg_opts[optnum].val;
3384
3385 switch (kwm) {
3386 case KWM_STD:
3387 curproxy->options |= cfg_opts[optnum].val;
3388 break;
3389 case KWM_NO:
3390 curproxy->no_options |= cfg_opts[optnum].val;
3391 break;
3392 case KWM_DEF: /* already cleared */
3393 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003394 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003395
Willy Tarreau93893792009-07-23 13:19:11 +02003396 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003397 }
3398 }
3399
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003400 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3401 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003402 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3403 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3404 file, linenum, cfg_opts2[optnum].name);
3405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
Willy Tarreau93893792009-07-23 13:19:11 +02003408 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3409 err_code |= ERR_WARN;
3410 goto out;
3411 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003412
Willy Tarreau3842f002009-06-14 11:39:52 +02003413 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3414 curproxy->options2 &= ~cfg_opts2[optnum].val;
3415
3416 switch (kwm) {
3417 case KWM_STD:
3418 curproxy->options2 |= cfg_opts2[optnum].val;
3419 break;
3420 case KWM_NO:
3421 curproxy->no_options2 |= cfg_opts2[optnum].val;
3422 break;
3423 case KWM_DEF: /* already cleared */
3424 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003425 }
Willy Tarreau93893792009-07-23 13:19:11 +02003426 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003427 }
3428 }
3429
Willy Tarreau3842f002009-06-14 11:39:52 +02003430 if (kwm != KWM_STD) {
3431 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003432 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003435 }
3436
Emeric Brun3a058f32009-06-30 18:26:00 +02003437 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003438 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003440 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003441 if (*(args[2]) != '\0') {
3442 if (!strcmp(args[2], "clf")) {
3443 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003444 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003445 } else {
3446 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003449 }
3450 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003451 if (curproxy->conf.logformat_string != default_http_log_format &&
3452 curproxy->conf.logformat_string != default_tcp_log_format &&
3453 curproxy->conf.logformat_string != clf_http_log_format)
3454 free(curproxy->conf.logformat_string);
3455 curproxy->conf.logformat_string = logformat;
3456
3457 free(curproxy->conf.lfs_file);
3458 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3459 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003460 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003461 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003463 if (curproxy->conf.logformat_string != default_http_log_format &&
3464 curproxy->conf.logformat_string != default_tcp_log_format &&
3465 curproxy->conf.logformat_string != clf_http_log_format)
3466 free(curproxy->conf.logformat_string);
3467 curproxy->conf.logformat_string = default_tcp_log_format;
3468
3469 free(curproxy->conf.lfs_file);
3470 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3471 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 else if (!strcmp(args[1], "tcpka")) {
3474 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003475 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003476 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003477
3478 if (curproxy->cap & PR_CAP_FE)
3479 curproxy->options |= PR_O_TCP_CLI_KA;
3480 if (curproxy->cap & PR_CAP_BE)
3481 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 }
3483 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003484 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_WARN;
3486
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003488 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003489 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003490 curproxy->options2 &= ~PR_O2_CHK_ANY;
3491 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 if (!*args[2]) { /* no argument */
3493 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3494 curproxy->check_len = strlen(DEF_CHECK_REQ);
3495 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003496 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 curproxy->check_req = (char *)malloc(reqlen);
3498 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003499 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003501 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 if (*args[4])
3503 reqlen += strlen(args[4]);
3504 else
3505 reqlen += strlen("HTTP/1.0");
3506
3507 curproxy->check_req = (char *)malloc(reqlen);
3508 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003509 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003511 }
3512 else if (!strcmp(args[1], "ssl-hello-chk")) {
3513 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003514 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003516
Willy Tarreaua534fea2008-08-03 12:19:50 +02003517 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003518 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003519 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003520 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 }
Willy Tarreau23677902007-05-08 23:50:35 +02003522 else if (!strcmp(args[1], "smtpchk")) {
3523 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003524 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003525 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003526 curproxy->options2 &= ~PR_O2_CHK_ANY;
3527 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003528
3529 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3530 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3531 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3532 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3533 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3534 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3535 curproxy->check_req = (char *)malloc(reqlen);
3536 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3537 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3538 } else {
3539 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3540 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3541 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3542 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3543 }
3544 }
3545 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003546 else if (!strcmp(args[1], "lb-agent-chk")) {
3547 /* use dynmaic health check */
3548 free(curproxy->check_req);
3549 curproxy->check_req = NULL;
3550 curproxy->options2 &= ~PR_O2_CHK_ANY;
3551 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3552 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003553 else if (!strcmp(args[1], "pgsql-check")) {
3554 /* use PostgreSQL request to check servers' health */
3555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3556 err_code |= ERR_WARN;
3557
3558 free(curproxy->check_req);
3559 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003560 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003561 curproxy->options2 |= PR_O2_PGSQL_CHK;
3562
3563 if (*(args[2])) {
3564 int cur_arg = 2;
3565
3566 while (*(args[cur_arg])) {
3567 if (strcmp(args[cur_arg], "user") == 0) {
3568 char * packet;
3569 uint32_t packet_len;
3570 uint32_t pv;
3571
3572 /* suboption header - needs additional argument for it */
3573 if (*(args[cur_arg+1]) == 0) {
3574 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3575 file, linenum, args[0], args[1], args[cur_arg]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579
3580 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3581 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3582 pv = htonl(0x30000); /* protocol version 3.0 */
3583
3584 packet = (char*) calloc(1, packet_len);
3585
3586 memcpy(packet + 4, &pv, 4);
3587
3588 /* copy "user" */
3589 memcpy(packet + 8, "user", 4);
3590
3591 /* copy username */
3592 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3593
3594 free(curproxy->check_req);
3595 curproxy->check_req = packet;
3596 curproxy->check_len = packet_len;
3597
3598 packet_len = htonl(packet_len);
3599 memcpy(packet, &packet_len, 4);
3600 cur_arg += 2;
3601 } else {
3602 /* unknown suboption - catchall */
3603 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3604 file, linenum, args[0], args[1]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608 } /* end while loop */
3609 }
3610 }
3611
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003612 else if (!strcmp(args[1], "redis-check")) {
3613 /* use REDIS PING request to check servers' health */
3614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3615 err_code |= ERR_WARN;
3616
3617 free(curproxy->check_req);
3618 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003619 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003620 curproxy->options2 |= PR_O2_REDIS_CHK;
3621
3622 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3623 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3624 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3625 }
3626
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003627 else if (!strcmp(args[1], "mysql-check")) {
3628 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003629 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3630 err_code |= ERR_WARN;
3631
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003632 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003633 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003634 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003635 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003636
3637 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3638 * const char mysql40_client_auth_pkt[] = {
3639 * "\x0e\x00\x00" // packet length
3640 * "\x01" // packet number
3641 * "\x00\x00" // client capabilities
3642 * "\x00\x00\x01" // max packet
3643 * "haproxy\x00" // username (null terminated string)
3644 * "\x00" // filler (always 0x00)
3645 * "\x01\x00\x00" // packet length
3646 * "\x00" // packet number
3647 * "\x01" // COM_QUIT command
3648 * };
3649 */
3650
3651 if (*(args[2])) {
3652 int cur_arg = 2;
3653
3654 while (*(args[cur_arg])) {
3655 if (strcmp(args[cur_arg], "user") == 0) {
3656 char *mysqluser;
3657 int packetlen, reqlen, userlen;
3658
3659 /* suboption header - needs additional argument for it */
3660 if (*(args[cur_arg+1]) == 0) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3662 file, linenum, args[0], args[1], args[cur_arg]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 mysqluser = args[cur_arg + 1];
3667 userlen = strlen(mysqluser);
3668 packetlen = userlen + 7;
3669 reqlen = packetlen + 9;
3670
3671 free(curproxy->check_req);
3672 curproxy->check_req = (char *)calloc(1, reqlen);
3673 curproxy->check_len = reqlen;
3674
3675 snprintf(curproxy->check_req, 4, "%c%c%c",
3676 ((unsigned char) packetlen & 0xff),
3677 ((unsigned char) (packetlen >> 8) & 0xff),
3678 ((unsigned char) (packetlen >> 16) & 0xff));
3679
3680 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003681 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003682 curproxy->check_req[8] = 1;
3683 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3684 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3685 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3686 cur_arg += 2;
3687 } else {
3688 /* unknown suboption - catchall */
3689 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3690 file, linenum, args[0], args[1]);
3691 err_code |= ERR_ALERT | ERR_FATAL;
3692 goto out;
3693 }
3694 } /* end while loop */
3695 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003696 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003697 else if (!strcmp(args[1], "ldap-check")) {
3698 /* use LDAP request to check servers' health */
3699 free(curproxy->check_req);
3700 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003701 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003702 curproxy->options2 |= PR_O2_LDAP_CHK;
3703
3704 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3705 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3706 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3707 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003708 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003709 int cur_arg;
3710
3711 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3712 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003713 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003714
Willy Tarreau87cf5142011-08-19 22:57:24 +02003715 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003716
3717 free(curproxy->fwdfor_hdr_name);
3718 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3719 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3720
3721 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3722 cur_arg = 2;
3723 while (*(args[cur_arg])) {
3724 if (!strcmp(args[cur_arg], "except")) {
3725 /* suboption except - needs additional argument for it */
3726 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3727 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3728 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003731 }
3732 /* flush useless bits */
3733 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003734 cur_arg += 2;
3735 } else if (!strcmp(args[cur_arg], "header")) {
3736 /* suboption header - needs additional argument for it */
3737 if (*(args[cur_arg+1]) == 0) {
3738 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3739 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003742 }
3743 free(curproxy->fwdfor_hdr_name);
3744 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3745 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3746 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003747 } else if (!strcmp(args[cur_arg], "if-none")) {
3748 curproxy->options &= ~PR_O_FF_ALWAYS;
3749 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003750 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003751 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003752 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003753 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003756 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003757 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003758 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003759 else if (!strcmp(args[1], "originalto")) {
3760 int cur_arg;
3761
3762 /* insert x-original-to field, but not for the IP address listed as an except.
3763 * set default options (ie: bitfield, header name, etc)
3764 */
3765
3766 curproxy->options |= PR_O_ORGTO;
3767
3768 free(curproxy->orgto_hdr_name);
3769 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3770 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3771
Willy Tarreau87cf5142011-08-19 22:57:24 +02003772 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003773 cur_arg = 2;
3774 while (*(args[cur_arg])) {
3775 if (!strcmp(args[cur_arg], "except")) {
3776 /* suboption except - needs additional argument for it */
3777 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3778 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3779 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003782 }
3783 /* flush useless bits */
3784 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3785 cur_arg += 2;
3786 } else if (!strcmp(args[cur_arg], "header")) {
3787 /* suboption header - needs additional argument for it */
3788 if (*(args[cur_arg+1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3790 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003793 }
3794 free(curproxy->orgto_hdr_name);
3795 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3796 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3797 cur_arg += 2;
3798 } else {
3799 /* unknown suboption - catchall */
3800 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3801 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003804 }
3805 } /* end while loop */
3806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 else {
3808 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 }
Willy Tarreau93893792009-07-23 13:19:11 +02003812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003814 else if (!strcmp(args[0], "default_backend")) {
3815 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003817
3818 if (*(args[1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003822 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003823 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003824 curproxy->defbe.name = strdup(args[1]);
3825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003830 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3831 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 /* enable reconnections to dispatch */
3834 curproxy->options |= PR_O_REDISP;
3835 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003836 else if (!strcmp(args[0], "http-check")) {
3837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003839
3840 if (strcmp(args[1], "disable-on-404") == 0) {
3841 /* enable a graceful server shutdown on an HTTP 404 response */
3842 curproxy->options |= PR_O_DISABLE404;
3843 }
Willy Tarreauef781042010-01-27 11:53:01 +01003844 else if (strcmp(args[1], "send-state") == 0) {
3845 /* enable emission of the apparent state of a server in HTTP checks */
3846 curproxy->options2 |= PR_O2_CHK_SNDST;
3847 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003848 else if (strcmp(args[1], "expect") == 0) {
3849 const char *ptr_arg;
3850 int cur_arg;
3851
3852 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3853 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857
3858 cur_arg = 2;
3859 /* consider exclamation marks, sole or at the beginning of a word */
3860 while (*(ptr_arg = args[cur_arg])) {
3861 while (*ptr_arg == '!') {
3862 curproxy->options2 ^= PR_O2_EXP_INV;
3863 ptr_arg++;
3864 }
3865 if (*ptr_arg)
3866 break;
3867 cur_arg++;
3868 }
3869 /* now ptr_arg points to the beginning of a word past any possible
3870 * exclamation mark, and cur_arg is the argument which holds this word.
3871 */
3872 if (strcmp(ptr_arg, "status") == 0) {
3873 if (!*(args[cur_arg + 1])) {
3874 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3875 file, linenum, args[0], args[1], ptr_arg);
3876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
3879 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003880 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003881 curproxy->expect_str = strdup(args[cur_arg + 1]);
3882 }
3883 else if (strcmp(ptr_arg, "string") == 0) {
3884 if (!*(args[cur_arg + 1])) {
3885 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3886 file, linenum, args[0], args[1], ptr_arg);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003891 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003892 curproxy->expect_str = strdup(args[cur_arg + 1]);
3893 }
3894 else if (strcmp(ptr_arg, "rstatus") == 0) {
3895 if (!*(args[cur_arg + 1])) {
3896 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3897 file, linenum, args[0], args[1], ptr_arg);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003902 free(curproxy->expect_str);
3903 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3904 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003905 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3906 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3907 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3908 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
3911 }
3912 }
3913 else if (strcmp(ptr_arg, "rstring") == 0) {
3914 if (!*(args[cur_arg + 1])) {
3915 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3916 file, linenum, args[0], args[1], ptr_arg);
3917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
3919 }
3920 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003921 free(curproxy->expect_str);
3922 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3923 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003924 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3925 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3926 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3927 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931 }
3932 else {
3933 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3934 file, linenum, args[0], args[1], ptr_arg);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003939 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003940 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 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003943 }
3944 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003945 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003946 if (curproxy == &defproxy) {
3947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003950 }
3951
Willy Tarreaub80c2302007-11-30 20:51:32 +01003952 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003954
3955 if (strcmp(args[1], "fail") == 0) {
3956 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003957 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003958 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3959 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003960 err_code |= ERR_ALERT | ERR_FATAL;
3961 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003962 }
3963
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003964 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3965 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3966 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003969 }
3970 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3971 }
3972 else {
3973 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003976 }
3977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978#ifdef TPROXY
3979 else if (!strcmp(args[0], "transparent")) {
3980 /* enable transparent proxy connections */
3981 curproxy->options |= PR_O_TRANSP;
3982 }
3983#endif
3984 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003985 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003987
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 if (*(args[1]) == 0) {
3989 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
3993 curproxy->maxconn = atol(args[1]);
3994 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003995 else if (!strcmp(args[0], "backlog")) { /* backlog */
3996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003998
3999 if (*(args[1]) == 0) {
4000 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004003 }
4004 curproxy->backlog = atol(args[1]);
4005 }
Willy Tarreau86034312006-12-29 00:10:33 +01004006 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004007 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004009
Willy Tarreau86034312006-12-29 00:10:33 +01004010 if (*(args[1]) == 0) {
4011 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004014 }
4015 curproxy->fullconn = atol(args[1]);
4016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4018 if (*(args[1]) == 0) {
4019 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004023 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4024 if (err) {
4025 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4026 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004029 }
4030 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 }
4032 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004033 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004034 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004035 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004036
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 if (curproxy == &defproxy) {
4038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004042 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004044
Willy Tarreau902636f2013-03-10 19:44:48 +01004045 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004046 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004047 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004049 goto out;
4050 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004051
4052 proto = protocol_by_family(sk->ss_family);
4053 if (!proto || !proto->connect) {
4054 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4055 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059
4060 if (port1 != port2) {
4061 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4062 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004066
4067 if (!port1) {
4068 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4069 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004073
Willy Tarreaud5191e72010-02-09 20:50:45 +01004074 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004075 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 }
4077 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004080
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004081 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4082 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004087 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004088 /**
4089 * The syntax for hash-type config element is
4090 * hash-type {map-based|consistent} [[<algo>] avalanche]
4091 *
4092 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4093 */
4094 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004095
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004096 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4097 err_code |= ERR_WARN;
4098
4099 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004100 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4101 }
4102 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004103 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4104 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004105 else if (strcmp(args[1], "avalanche") == 0) {
4106 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]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004109 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004110 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004111 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
4114 }
Bhaskar98634f02013-10-29 23:30:51 -04004115
4116 /* set the hash function to use */
4117 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004118 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004119 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004120
4121 /* if consistent with no argument, then avalanche modifier is also applied */
4122 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4123 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004124 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004125 /* set the hash function */
4126 if (!strcmp(args[2], "sdbm")) {
4127 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4128 }
4129 else if (!strcmp(args[2], "djb2")) {
4130 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004131 } else if (!strcmp(args[2], "wt6")) {
4132 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004133 }
4134 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004135 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 -05004136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
4138 }
4139
4140 /* set the hash modifier */
4141 if (!strcmp(args[3], "avalanche")) {
4142 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4143 }
4144 else if (*args[3]) {
4145 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
4148 }
Bhaskar98634f02013-10-29 23:30:51 -04004149 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004150 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004151 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 short realport = 0;
4154 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004156 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004157 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004161 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163
4164 if (!*args[2]) {
4165 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004170
4171 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004172 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004173 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4174 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004177 }
4178
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004180 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004181 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004182 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004183
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004184 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4185 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4186 err_code |= ERR_ALERT | ERR_ABORT;
4187 goto out;
4188 }
4189
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004190 /* the servers are linked backwards first */
4191 newsrv->next = curproxy->srv;
4192 curproxy->srv = newsrv;
4193 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004194 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004195 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004197 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004198 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004199 LIST_INIT(&newsrv->pendconns);
4200 do_check = 0;
4201 newsrv->state = SRV_RUNNING; /* early server setup */
4202 newsrv->last_change = now.tv_sec;
4203 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004205 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004206 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004207 * - IP: => port=+0, relative
4208 * - IP:N => port=N, absolute
4209 * - IP:+N => port=+N, relative
4210 * - IP:-N => port=-N, relative
4211 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004212 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004213 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004214 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004215 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004216 goto out;
4217 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004218
4219 proto = protocol_by_family(sk->ss_family);
4220 if (!proto || !proto->connect) {
4221 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4222 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004226
4227 if (!port1 || !port2) {
4228 /* no port specified, +offset, -offset */
4229 newsrv->state |= SRV_MAPPORTS;
4230 }
4231 else if (port1 != port2) {
4232 /* port range */
4233 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4234 file, linenum, args[0], args[1], args[2]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238 else {
4239 /* used by checks */
4240 realport = port1;
4241 }
4242
Willy Tarreaud5191e72010-02-09 20:50:45 +01004243 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004244 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4245 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004246
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004247 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004248 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4249 file, linenum, newsrv->addr.ss_family, args[2]);
4250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004253
Simon Horman66183002013-02-23 10:16:43 +09004254 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004255 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004256 newsrv->check.inter = curproxy->defsrv.check.inter;
4257 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4258 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004259 newsrv->rise = curproxy->defsrv.rise;
4260 newsrv->fall = curproxy->defsrv.fall;
4261 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4262 newsrv->minconn = curproxy->defsrv.minconn;
4263 newsrv->maxconn = curproxy->defsrv.maxconn;
4264 newsrv->slowstart = curproxy->defsrv.slowstart;
4265 newsrv->onerror = curproxy->defsrv.onerror;
4266 newsrv->consecutive_errors_limit
4267 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004268#ifdef OPENSSL
4269 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4270#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004271 newsrv->uweight = newsrv->iweight
4272 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004274 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004275
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004276 cur_arg = 3;
4277 } else {
4278 newsrv = &curproxy->defsrv;
4279 cur_arg = 1;
4280 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004281
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004283 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 newsrv->cookie = strdup(args[cur_arg + 1]);
4285 newsrv->cklen = strlen(args[cur_arg + 1]);
4286 cur_arg += 2;
4287 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004288 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004289 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4290 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4291 cur_arg += 2;
4292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004294 if (!*args[cur_arg + 1]) {
4295 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4296 file, linenum, args[cur_arg]);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004302 if (newsrv->rise <= 0) {
4303 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4304 file, linenum, args[cur_arg]);
4305 err_code |= ERR_ALERT | ERR_FATAL;
4306 goto out;
4307 }
4308
Willy Tarreau96839092010-03-29 10:02:24 +02004309 if (newsrv->health)
4310 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 cur_arg += 2;
4312 }
4313 else if (!strcmp(args[cur_arg], "fall")) {
4314 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004315
4316 if (!*args[cur_arg + 1]) {
4317 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4318 file, linenum, args[cur_arg]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322
4323 if (newsrv->fall <= 0) {
4324 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4325 file, linenum, args[cur_arg]);
4326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
4328 }
4329
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 cur_arg += 2;
4331 }
4332 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004333 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4334 if (err) {
4335 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4336 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004339 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004340 if (val <= 0) {
4341 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4342 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004345 }
Simon Horman66183002013-02-23 10:16:43 +09004346 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 cur_arg += 2;
4348 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004349 else if (!strcmp(args[cur_arg], "fastinter")) {
4350 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4351 if (err) {
4352 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4353 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004356 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004357 if (val <= 0) {
4358 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4359 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004360 err_code |= ERR_ALERT | ERR_FATAL;
4361 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004362 }
Simon Horman66183002013-02-23 10:16:43 +09004363 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004364 cur_arg += 2;
4365 }
4366 else if (!strcmp(args[cur_arg], "downinter")) {
4367 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4368 if (err) {
4369 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4370 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004373 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004374 if (val <= 0) {
4375 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4376 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004379 }
Simon Horman66183002013-02-23 10:16:43 +09004380 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004381 cur_arg += 2;
4382 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004383 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004384 struct sockaddr_storage *sk;
4385 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004386 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004387
Willy Tarreau902636f2013-03-10 19:44:48 +01004388 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004389 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004390 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004391 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004392 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004393 goto out;
4394 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004395
4396 proto = protocol_by_family(sk->ss_family);
4397 if (!proto || !proto->connect) {
4398 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004399 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004403
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004404 if (port1 != port2) {
4405 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4406 file, linenum, args[cur_arg], args[cur_arg + 1]);
4407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
4409 }
4410
Simon Horman66183002013-02-23 10:16:43 +09004411 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004412 cur_arg += 2;
4413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004415 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 cur_arg += 2;
4417 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004418 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 newsrv->state |= SRV_BACKUP;
4420 cur_arg ++;
4421 }
Simon Hormanfa461682011-06-25 09:39:49 +09004422 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4423 newsrv->state |= SRV_NON_STICK;
4424 cur_arg ++;
4425 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004426 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4427 newsrv->state |= SRV_SEND_PROXY;
4428 cur_arg ++;
4429 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004430 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4431 newsrv->check.send_proxy = 1;
4432 cur_arg ++;
4433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 else if (!strcmp(args[cur_arg], "weight")) {
4435 int w;
4436 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004437 if (w < 0 || w > SRV_UWGHT_MAX) {
4438 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4439 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004443 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 cur_arg += 2;
4445 }
4446 else if (!strcmp(args[cur_arg], "minconn")) {
4447 newsrv->minconn = atol(args[cur_arg + 1]);
4448 cur_arg += 2;
4449 }
4450 else if (!strcmp(args[cur_arg], "maxconn")) {
4451 newsrv->maxconn = atol(args[cur_arg + 1]);
4452 cur_arg += 2;
4453 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004454 else if (!strcmp(args[cur_arg], "maxqueue")) {
4455 newsrv->maxqueue = atol(args[cur_arg + 1]);
4456 cur_arg += 2;
4457 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004458 else if (!strcmp(args[cur_arg], "slowstart")) {
4459 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004460 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004461 if (err) {
4462 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4463 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004466 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004467 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004468 cur_arg += 2;
4469 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004470 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004471
4472 if (!*args[cur_arg + 1]) {
4473 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004477 }
4478
4479 newsrv->trackit = strdup(args[cur_arg + 1]);
4480
4481 cur_arg += 2;
4482 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004483 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 global.maxsock++;
4485 do_check = 1;
4486 cur_arg += 1;
4487 }
Willy Tarreau96839092010-03-29 10:02:24 +02004488 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4489 newsrv->state |= SRV_MAINTAIN;
4490 newsrv->state &= ~SRV_RUNNING;
4491 newsrv->health = 0;
4492 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004493 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004494 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004495 if (!strcmp(args[cur_arg + 1], "none"))
4496 newsrv->observe = HANA_OBS_NONE;
4497 else if (!strcmp(args[cur_arg + 1], "layer4"))
4498 newsrv->observe = HANA_OBS_LAYER4;
4499 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4500 if (curproxy->mode != PR_MODE_HTTP) {
4501 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4502 file, linenum, args[cur_arg + 1]);
4503 err_code |= ERR_ALERT;
4504 }
4505 newsrv->observe = HANA_OBS_LAYER7;
4506 }
4507 else {
4508 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004509 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004510 file, linenum, args[cur_arg], args[cur_arg + 1]);
4511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
4513 }
4514
4515 cur_arg += 2;
4516 }
4517 else if (!strcmp(args[cur_arg], "on-error")) {
4518 if (!strcmp(args[cur_arg + 1], "fastinter"))
4519 newsrv->onerror = HANA_ONERR_FASTINTER;
4520 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4521 newsrv->onerror = HANA_ONERR_FAILCHK;
4522 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4523 newsrv->onerror = HANA_ONERR_SUDDTH;
4524 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4525 newsrv->onerror = HANA_ONERR_MARKDWN;
4526 else {
4527 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004528 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004529 file, linenum, args[cur_arg], args[cur_arg + 1]);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
4532 }
4533
4534 cur_arg += 2;
4535 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004536 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4537 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4538 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4539 else {
4540 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4541 file, linenum, args[cur_arg], args[cur_arg + 1]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545
4546 cur_arg += 2;
4547 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004548 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4549 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4550 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4551 else {
4552 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4553 file, linenum, args[cur_arg], args[cur_arg + 1]);
4554 err_code |= ERR_ALERT | ERR_FATAL;
4555 goto out;
4556 }
4557
4558 cur_arg += 2;
4559 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004560 else if (!strcmp(args[cur_arg], "error-limit")) {
4561 if (!*args[cur_arg + 1]) {
4562 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4563 file, linenum, args[cur_arg]);
4564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
4566 }
4567
4568 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4569
4570 if (newsrv->consecutive_errors_limit <= 0) {
4571 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4572 file, linenum, args[cur_arg]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004576 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004577 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004578 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004579 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004580 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004581 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004582
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004584 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4585 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004589
Willy Tarreauef9a3602012-12-08 22:29:20 +01004590 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004591 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004592 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004593 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004594 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004595 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004596 goto out;
4597 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004598
4599 proto = protocol_by_family(sk->ss_family);
4600 if (!proto || !proto->connect) {
4601 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4602 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
4605 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004606
Willy Tarreauef9a3602012-12-08 22:29:20 +01004607 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004608
4609 if (port_low != port_high) {
4610 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004611
4612 if (!port_low || !port_high) {
4613 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4614 file, linenum, args[cur_arg], args[cur_arg + 1]);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
4618
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004619 if (port_low <= 0 || port_low > 65535 ||
4620 port_high <= 0 || port_high > 65535 ||
4621 port_low > port_high) {
4622 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4623 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004626 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004627 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4628 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4629 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004630 }
4631
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004633 while (*(args[cur_arg])) {
4634 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004635#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4636#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004637 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004638 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4639 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004642 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004643#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004644 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004645 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004646 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004649 }
4650 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004651 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4652 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004653 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004654 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4655 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004656 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4657 char *name, *end;
4658
4659 name = args[cur_arg+1] + 7;
4660 while (isspace(*name))
4661 name++;
4662
4663 end = name;
4664 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4665 end++;
4666
Willy Tarreauef9a3602012-12-08 22:29:20 +01004667 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4668 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4669 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4670 newsrv->conn_src.bind_hdr_len = end - name;
4671 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4672 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4673 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004674
4675 /* now look for an occurrence number */
4676 while (isspace(*end))
4677 end++;
4678 if (*end == ',') {
4679 end++;
4680 name = end;
4681 if (*end == '-')
4682 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004683 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004684 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004685 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004686 }
4687
Willy Tarreauef9a3602012-12-08 22:29:20 +01004688 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004689 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4690 " occurrences values smaller than %d.\n",
4691 file, linenum, MAX_HDR_HISTORY);
4692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
4694 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004695 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004696 struct sockaddr_storage *sk;
4697 int port1, port2;
4698
Willy Tarreau902636f2013-03-10 19:44:48 +01004699 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004700 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004701 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004702 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004703 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004704 goto out;
4705 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004706
4707 proto = protocol_by_family(sk->ss_family);
4708 if (!proto || !proto->connect) {
4709 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4710 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
4713 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004714
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004715 if (port1 != port2) {
4716 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4717 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004721 newsrv->conn_src.tproxy_addr = *sk;
4722 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004723 }
4724 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004725#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004726 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004728 cur_arg += 2;
4729 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004730#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004731 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004732 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004735#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004736 } /* "usesrc" */
4737
4738 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4739#ifdef SO_BINDTODEVICE
4740 if (!*args[cur_arg + 1]) {
4741 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4742 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004745 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004746 free(newsrv->conn_src.iface_name);
4747 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4748 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004749 global.last_checks |= LSTCHK_NETADM;
4750#else
4751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004755#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004756 cur_arg += 2;
4757 continue;
4758 }
4759 /* this keyword in not an option of "source" */
4760 break;
4761 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004762 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004763 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004764 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4765 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004770 static int srv_dumped;
4771 struct srv_kw *kw;
4772 char *err;
4773
4774 kw = srv_find_kw(args[cur_arg]);
4775 if (kw) {
4776 char *err = NULL;
4777 int code;
4778
4779 if (!kw->parse) {
4780 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4781 file, linenum, args[0], args[1], args[cur_arg]);
4782 cur_arg += 1 + kw->skip ;
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
4786
4787 if (defsrv && !kw->default_ok) {
4788 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4789 file, linenum, args[0], args[1], args[cur_arg]);
4790 cur_arg += 1 + kw->skip ;
4791 err_code |= ERR_ALERT;
4792 continue;
4793 }
4794
4795 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4796 err_code |= code;
4797
4798 if (code) {
4799 if (err && *err) {
4800 indent_msg(&err, 2);
4801 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4802 }
4803 else
4804 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4805 file, linenum, args[0], args[1], args[cur_arg]);
4806 if (code & ERR_FATAL) {
4807 free(err);
4808 cur_arg += 1 + kw->skip;
4809 goto out;
4810 }
4811 }
4812 free(err);
4813 cur_arg += 1 + kw->skip;
4814 continue;
4815 }
4816
4817 err = NULL;
4818 if (!srv_dumped) {
4819 srv_dump_kws(&err);
4820 indent_msg(&err, 4);
4821 srv_dumped = 1;
4822 }
4823
4824 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4825 file, linenum, args[0], args[1], args[cur_arg],
4826 err ? " Registered keywords :" : "", err ? err : "");
4827 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004828
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 }
4832 }
4833
4834 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004835 if (newsrv->trackit) {
4836 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4837 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004840 }
4841
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004842 /* If neither a port nor an addr was specified and no check transport
4843 * layer is forced, then the transport layer used by the checks is the
4844 * same as for the production traffic. Otherwise we use raw_sock by
4845 * default, unless one is specified.
4846 */
Simon Horman66183002013-02-23 10:16:43 +09004847 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004848#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004849 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004850#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004851 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4852 }
Simon Horman66183002013-02-23 10:16:43 +09004853 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004854 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09004855 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004856
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004857 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004858 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004859
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004860 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004861 /* not yet valid, because no port was set on
4862 * the server either. We'll check if we have
4863 * a known port on the first listener.
4864 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004865 struct listener *l;
4866
4867 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004868 newsrv->check.port = get_host_port(&l->addr);
4869 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004870 break;
4871 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004872 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004873 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4875 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004879
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004880 /* Allocate buffer for check requests... */
4881 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004882 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4883 err_code |= ERR_ALERT | ERR_ABORT;
4884 goto out;
4885 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004886 newsrv->check.bi->size = global.tune.chksize;
4887
4888 /* Allocate buffer for check responses... */
4889 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4890 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4891 err_code |= ERR_ALERT | ERR_ABORT;
4892 goto out;
4893 }
4894 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004895
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004896 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004897 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004898 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4899 err_code |= ERR_ALERT | ERR_ABORT;
4900 goto out;
4901 }
4902
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004903 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4904 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman4a741432013-02-23 15:35:38 +09004905 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
Simon Horman66183002013-02-23 10:16:43 +09004906 newsrv->check.server = newsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 newsrv->state |= SRV_CHECKED;
4908 }
4909
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004910 if (!defsrv) {
4911 if (newsrv->state & SRV_BACKUP)
4912 curproxy->srv_bck++;
4913 else
4914 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004915
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004916 newsrv->prev_state = newsrv->state;
4917 }
William Lallemanda73203e2012-03-12 12:48:57 +01004918 }
4919
4920 else if (strcmp(args[0], "unique-id-format") == 0) {
4921 if (!*(args[1])) {
4922 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
William Lallemand3203ff42012-11-11 17:30:56 +01004926 if (*(args[2])) {
4927 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
4930 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004931 free(curproxy->conf.uniqueid_format_string);
4932 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004933
Willy Tarreau62a61232013-04-12 18:13:46 +02004934 free(curproxy->conf.uif_file);
4935 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4936 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004937 }
William Lallemanda73203e2012-03-12 12:48:57 +01004938
4939 else if (strcmp(args[0], "unique-id-header") == 0) {
4940 if (!*(args[1])) {
4941 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
4944 }
4945 free(curproxy->header_unique_id);
4946 curproxy->header_unique_id = strdup(args[1]);
4947 }
4948
William Lallemand723b73a2012-02-08 16:37:49 +01004949 else if (strcmp(args[0], "log-format") == 0) {
4950 if (!*(args[1])) {
4951 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
4954 }
William Lallemand3203ff42012-11-11 17:30:56 +01004955 if (*(args[2])) {
4956 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
4959 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004960
Willy Tarreau62a61232013-04-12 18:13:46 +02004961 if (curproxy->conf.logformat_string != default_http_log_format &&
4962 curproxy->conf.logformat_string != default_tcp_log_format &&
4963 curproxy->conf.logformat_string != clf_http_log_format)
4964 free(curproxy->conf.logformat_string);
4965 curproxy->conf.logformat_string = strdup(args[1]);
4966
4967 free(curproxy->conf.lfs_file);
4968 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4969 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004970
4971 /* get a chance to improve log-format error reporting by
4972 * reporting the correct line-number when possible.
4973 */
4974 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4975 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4976 file, linenum, curproxy->id);
4977 err_code |= ERR_WARN;
4978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
William Lallemand723b73a2012-02-08 16:37:49 +01004980
William Lallemand0f99e342011-10-12 17:50:54 +02004981 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4982 /* delete previous herited or defined syslog servers */
4983 struct logsrv *back;
4984
4985 if (*(args[1]) != 0) {
4986 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
4990
William Lallemand723b73a2012-02-08 16:37:49 +01004991 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4992 LIST_DEL(&tmplogsrv->list);
4993 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004994 }
4995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004997 struct logsrv *logsrv;
4998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005000 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005001 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005002 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005003 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005004 LIST_INIT(&node->list);
5005 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
5008 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005009 struct sockaddr_storage *sk;
5010 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005011
5012 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013
William Lallemand0f99e342011-10-12 17:50:54 +02005014 logsrv->facility = get_log_facility(args[2]);
5015 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
5021
William Lallemand0f99e342011-10-12 17:50:54 +02005022 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005024 logsrv->level = get_log_level(args[3]);
5025 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 }
5032
William Lallemand0f99e342011-10-12 17:50:54 +02005033 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005034 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005035 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005036 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005037 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
5040
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005041 }
5042 }
5043
Willy Tarreau902636f2013-03-10 19:44:48 +01005044 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005045 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005046 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005047 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005048 goto out;
5049 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005050
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005051 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005052
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005053 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005054 if (port1 != port2) {
5055 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5056 file, linenum, args[0], args[1]);
5057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
5059 }
5060
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005061 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005062 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
William Lallemand0f99e342011-10-12 17:50:54 +02005064
5065 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 else {
5068 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5069 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 }
5073 }
5074 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005075 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005076 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005077 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005078 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005079
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005082
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005084 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5085 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005089
5090 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005091 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5092 free(curproxy->conn_src.iface_name);
5093 curproxy->conn_src.iface_name = NULL;
5094 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005095
Willy Tarreau902636f2013-03-10 19:44:48 +01005096 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005097 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005098 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005099 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005100 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005101 goto out;
5102 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005103
5104 proto = protocol_by_family(sk->ss_family);
5105 if (!proto || !proto->connect) {
5106 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005111
5112 if (port1 != port2) {
5113 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5114 file, linenum, args[0], args[1]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
Willy Tarreauef9a3602012-12-08 22:29:20 +01005119 curproxy->conn_src.source_addr = *sk;
5120 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005121
5122 cur_arg = 2;
5123 while (*(args[cur_arg])) {
5124 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005125#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5126#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005127 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005128 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5129 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005132 }
5133#endif
5134 if (!*args[cur_arg + 1]) {
5135 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5136 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005139 }
5140
5141 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005142 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5143 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005144 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005145 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5146 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005147 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5148 char *name, *end;
5149
5150 name = args[cur_arg+1] + 7;
5151 while (isspace(*name))
5152 name++;
5153
5154 end = name;
5155 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5156 end++;
5157
Willy Tarreauef9a3602012-12-08 22:29:20 +01005158 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5159 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5160 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5161 curproxy->conn_src.bind_hdr_len = end - name;
5162 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5163 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5164 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005165
5166 /* now look for an occurrence number */
5167 while (isspace(*end))
5168 end++;
5169 if (*end == ',') {
5170 end++;
5171 name = end;
5172 if (*end == '-')
5173 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005174 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005175 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005176 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005177 }
5178
Willy Tarreauef9a3602012-12-08 22:29:20 +01005179 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005180 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5181 " occurrences values smaller than %d.\n",
5182 file, linenum, MAX_HDR_HISTORY);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005186 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005187 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005188
Willy Tarreau902636f2013-03-10 19:44:48 +01005189 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005190 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005191 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005192 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005193 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005194 goto out;
5195 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005196
5197 proto = protocol_by_family(sk->ss_family);
5198 if (!proto || !proto->connect) {
5199 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5200 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
5203 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005204
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005205 if (port1 != port2) {
5206 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5207 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005211 curproxy->conn_src.tproxy_addr = *sk;
5212 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005213 }
5214 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005215#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005216 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005217#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005218#else /* no TPROXY support */
5219 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005220 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005223#endif
5224 cur_arg += 2;
5225 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005226 }
5227
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005228 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5229#ifdef SO_BINDTODEVICE
5230 if (!*args[cur_arg + 1]) {
5231 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5232 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005235 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005236 free(curproxy->conn_src.iface_name);
5237 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5238 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005239 global.last_checks |= LSTCHK_NETADM;
5240#else
5241 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5242 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005245#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005246 cur_arg += 2;
5247 continue;
5248 }
5249 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005250 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005255 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5256 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5257 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5264 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268
5269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005270 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005271 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005277 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005278 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
5282 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005284 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005285 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
5289 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005291 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005298 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005303 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005305 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005309 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005310 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005312 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005313 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005315 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005316 }
5317 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005319 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005320 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005322 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331
5332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005333 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005334 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005340 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
5345 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005347 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005354 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 }
5359 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005361 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005366 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005368 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005371 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005374 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005375
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 if (curproxy == &defproxy) {
5377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_ALERT | ERR_FATAL;
5379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005381 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 if (*(args[1]) == 0) {
5385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005386 err_code |= ERR_ALERT | ERR_FATAL;
5387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005389
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005390 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5392 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5393 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
5396 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005397 err_code |= warnif_cond_conflicts(cond,
5398 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5399 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005400 }
5401 else if (*args[2]) {
5402 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5403 file, linenum, args[0], args[2]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005408 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005409 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005410 wl->s = strdup(args[1]);
5411 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005412 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
5414 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005415 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005421
Willy Tarreauade5ec42010-01-28 19:33:49 +01005422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005423 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005424 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
5428 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005430 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005434 }
5435 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005437 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 }
5442 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005443 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 }
5449
Willy Tarreauade5ec42010-01-28 19:33:49 +01005450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005451 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005452 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 }
5456 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005458 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005459 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 }
5463 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005465 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 }
5470 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005471 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005472
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 if (curproxy == &defproxy) {
5474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005478 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 if (*(args[1]) == 0) {
5482 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 }
5486
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005487 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005488 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5489 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5490 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005494 err_code |= warnif_cond_conflicts(cond,
5495 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5496 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005497 }
5498 else if (*args[2]) {
5499 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5500 file, linenum, args[0], args[2]);
5501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
5503 }
5504
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005505 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005506 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005507 wl->s = strdup(args[1]);
5508 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 }
5510 else if (!strcmp(args[0], "errorloc") ||
5511 !strcmp(args[0], "errorloc302") ||
5512 !strcmp(args[0], "errorloc303")) { /* error location */
5513 int errnum, errlen;
5514 char *err;
5515
Willy Tarreau977b8e42006-12-29 14:19:17 +01005516 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005517 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005518
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005520 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524
5525 errnum = atol(args[1]);
5526 if (!strcmp(args[0], "errorloc303")) {
5527 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5528 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5529 } else {
5530 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5531 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5532 }
5533
Willy Tarreau0f772532006-12-23 20:51:41 +01005534 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5535 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005536 chunk_destroy(&curproxy->errmsg[rc]);
5537 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005538 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005541
5542 if (rc >= HTTP_ERR_SIZE) {
5543 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5544 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 free(err);
5546 }
5547 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005548 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5549 int errnum, errlen, fd;
5550 char *err;
5551 struct stat stat;
5552
5553 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005554 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005555
5556 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005557 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005558 err_code |= ERR_ALERT | ERR_FATAL;
5559 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005560 }
5561
5562 fd = open(args[2], O_RDONLY);
5563 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5564 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5565 file, linenum, args[2], args[1]);
5566 if (fd >= 0)
5567 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005570 }
5571
Willy Tarreau27a674e2009-08-17 07:23:33 +02005572 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005573 errlen = stat.st_size;
5574 } else {
5575 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005576 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005578 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005579 }
5580
5581 err = malloc(errlen); /* malloc() must succeed during parsing */
5582 errnum = read(fd, err, errlen);
5583 if (errnum != errlen) {
5584 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5585 file, linenum, args[2], args[1]);
5586 close(fd);
5587 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005590 }
5591 close(fd);
5592
5593 errnum = atol(args[1]);
5594 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5595 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005596 chunk_destroy(&curproxy->errmsg[rc]);
5597 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005598 break;
5599 }
5600 }
5601
5602 if (rc >= HTTP_ERR_SIZE) {
5603 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5604 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005605 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005606 free(err);
5607 }
5608 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005609 else if (!strcmp(args[0], "compression")) {
5610 struct comp *comp;
5611 if (curproxy->comp == NULL) {
5612 comp = calloc(1, sizeof(struct comp));
5613 curproxy->comp = comp;
5614 } else {
5615 comp = curproxy->comp;
5616 }
5617
5618 if (!strcmp(args[1], "algo")) {
5619 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005620 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005621
William Lallemand82fe75c2012-10-23 10:25:10 +02005622 cur_arg = 2;
5623 if (!*args[cur_arg]) {
5624 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5625 file, linenum, args[0]);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629 while (*(args[cur_arg])) {
5630 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5631 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5632 file, linenum, args[0], args[cur_arg]);
5633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
William Lallemand552df672012-11-07 13:21:47 +01005636 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5637 curproxy->comp->algos->end(&ctx);
5638 } else {
5639 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5640 file, linenum, args[0], args[cur_arg]);
5641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
5643 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005644 cur_arg ++;
5645 continue;
5646 }
5647 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005648 else if (!strcmp(args[1], "offload")) {
5649 comp->offload = 1;
5650 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005651 else if (!strcmp(args[1], "type")) {
5652 int cur_arg;
5653 cur_arg = 2;
5654 if (!*args[cur_arg]) {
5655 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5656 file, linenum, args[0]);
5657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
5659 }
5660 while (*(args[cur_arg])) {
5661 comp_append_type(comp, args[cur_arg]);
5662 cur_arg ++;
5663 continue;
5664 }
5665 }
5666 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005667 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005668 file, linenum, args[0]);
5669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
5671 }
5672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005674 struct cfg_kw_list *kwl;
5675 int index;
5676
5677 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5678 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5679 if (kwl->kw[index].section != CFG_LISTEN)
5680 continue;
5681 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5682 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005683 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005684 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005685 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005688 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005689 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005690 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= ERR_WARN;
5692 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005693 }
Willy Tarreau93893792009-07-23 13:19:11 +02005694 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005695 }
5696 }
5697 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005698
Willy Tarreau6daf3432008-01-22 16:44:08 +01005699 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005700 err_code |= ERR_ALERT | ERR_FATAL;
5701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
Willy Tarreau93893792009-07-23 13:19:11 +02005703 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005704 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005705 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706}
5707
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005708int
5709cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5710{
5711
5712 int err_code = 0;
5713 const char *err;
5714
5715 if (!strcmp(args[0], "userlist")) { /* new userlist */
5716 struct userlist *newul;
5717
5718 if (!*args[1]) {
5719 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5720 file, linenum, args[0]);
5721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
5723 }
5724
5725 err = invalid_char(args[1]);
5726 if (err) {
5727 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5728 file, linenum, *err, args[0], args[1]);
5729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
5731 }
5732
5733 for (newul = userlist; newul; newul = newul->next)
5734 if (!strcmp(newul->name, args[1])) {
5735 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5736 file, linenum, args[1]);
5737 err_code |= ERR_WARN;
5738 goto out;
5739 }
5740
5741 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5742 if (!newul) {
5743 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5744 err_code |= ERR_ALERT | ERR_ABORT;
5745 goto out;
5746 }
5747
5748 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5749 newul->name = strdup(args[1]);
5750
5751 if (!newul->groupusers | !newul->name) {
5752 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5753 err_code |= ERR_ALERT | ERR_ABORT;
5754 goto out;
5755 }
5756
5757 newul->next = userlist;
5758 userlist = newul;
5759
5760 } else if (!strcmp(args[0], "group")) { /* new group */
5761 int cur_arg, i;
5762 const char *err;
5763
5764 if (!*args[1]) {
5765 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5766 file, linenum, args[0]);
5767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
5769 }
5770
5771 err = invalid_char(args[1]);
5772 if (err) {
5773 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5774 file, linenum, *err, args[0], args[1]);
5775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
5777 }
5778
5779 for(i = 0; i < userlist->grpcnt; i++)
5780 if (!strcmp(userlist->groups[i], args[1])) {
5781 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5782 file, linenum, args[1], userlist->name);
5783 err_code |= ERR_ALERT;
5784 goto out;
5785 }
5786
5787 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5788 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5789 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793
5794 cur_arg = 2;
5795
5796 while (*args[cur_arg]) {
5797 if (!strcmp(args[cur_arg], "users")) {
5798 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5799 cur_arg += 2;
5800 continue;
5801 } else {
5802 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5803 file, linenum, args[0]);
5804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
5806 }
5807 }
5808
5809 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5810 } else if (!strcmp(args[0], "user")) { /* new user */
5811 struct auth_users *newuser;
5812 int cur_arg;
5813
5814 if (!*args[1]) {
5815 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5816 file, linenum, args[0]);
5817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
5819 }
5820
5821 for (newuser = userlist->users; newuser; newuser = newuser->next)
5822 if (!strcmp(newuser->user, args[1])) {
5823 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5824 file, linenum, args[1], userlist->name);
5825 err_code |= ERR_ALERT;
5826 goto out;
5827 }
5828
5829 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5830 if (!newuser) {
5831 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5832 err_code |= ERR_ALERT | ERR_ABORT;
5833 goto out;
5834 }
5835
5836 newuser->user = strdup(args[1]);
5837
5838 newuser->next = userlist->users;
5839 userlist->users = newuser;
5840
5841 cur_arg = 2;
5842
5843 while (*args[cur_arg]) {
5844 if (!strcmp(args[cur_arg], "password")) {
5845#ifndef CONFIG_HAP_CRYPT
5846 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5847 file, linenum);
5848 err_code |= ERR_ALERT;
5849#endif
5850 newuser->pass = strdup(args[cur_arg + 1]);
5851 cur_arg += 2;
5852 continue;
5853 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5854 newuser->pass = strdup(args[cur_arg + 1]);
5855 newuser->flags |= AU_O_INSECURE;
5856 cur_arg += 2;
5857 continue;
5858 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005859 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005860 cur_arg += 2;
5861 continue;
5862 } else {
5863 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5864 file, linenum, args[0]);
5865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
5867 }
5868 }
5869 } else {
5870 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5871 err_code |= ERR_ALERT | ERR_FATAL;
5872 }
5873
5874out:
5875 return err_code;
5876}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877
5878/*
5879 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005880 * Returns the error code, 0 if OK, or any combination of :
5881 * - ERR_ABORT: must abort ASAP
5882 * - ERR_FATAL: we can continue parsing but not start the service
5883 * - ERR_WARN: a warning has been emitted
5884 * - ERR_ALERT: an alert has been emitted
5885 * Only the two first ones can stop processing, the two others are just
5886 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005888int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005890 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 FILE *f;
5892 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005893 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005894 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 if ((f=fopen(file,"r")) == NULL)
5897 return -1;
5898
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005899 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005900 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005901 char *end;
5902 char *args[MAX_LINE_ARGS + 1];
5903 char *line = thisline;
5904
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 linenum++;
5906
5907 end = line + strlen(line);
5908
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005909 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5910 /* Check if we reached the limit and the last char is not \n.
5911 * Watch out for the last line without the terminating '\n'!
5912 */
5913 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005914 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005916 }
5917
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005919 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 line++;
5921
5922 arg = 0;
5923 args[arg] = line;
5924
5925 while (*line && arg < MAX_LINE_ARGS) {
5926 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5927 * C equivalent value. Other combinations left unchanged (eg: \1).
5928 */
5929 if (*line == '\\') {
5930 int skip = 0;
5931 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5932 *line = line[1];
5933 skip = 1;
5934 }
5935 else if (line[1] == 'r') {
5936 *line = '\r';
5937 skip = 1;
5938 }
5939 else if (line[1] == 'n') {
5940 *line = '\n';
5941 skip = 1;
5942 }
5943 else if (line[1] == 't') {
5944 *line = '\t';
5945 skip = 1;
5946 }
5947 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005948 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 unsigned char hex1, hex2;
5950 hex1 = toupper(line[2]) - '0';
5951 hex2 = toupper(line[3]) - '0';
5952 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5953 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5954 *line = (hex1<<4) + hex2;
5955 skip = 3;
5956 }
5957 else {
5958 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005959 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 }
5961 }
5962 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005963 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 end -= skip;
5965 }
5966 line++;
5967 }
5968 else if (*line == '#' || *line == '\n' || *line == '\r') {
5969 /* end of string, end of loop */
5970 *line = 0;
5971 break;
5972 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005973 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005975 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005976 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 line++;
5978 args[++arg] = line;
5979 }
5980 else {
5981 line++;
5982 }
5983 }
5984
5985 /* empty line */
5986 if (!**args)
5987 continue;
5988
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005989 if (*line) {
5990 /* we had to stop due to too many args.
5991 * Let's terminate the string, print the offending part then cut the
5992 * last arg.
5993 */
5994 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5995 line++;
5996 *line = '\0';
5997
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005998 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005999 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006000 err_code |= ERR_ALERT | ERR_FATAL;
6001 args[arg] = line;
6002 }
6003
Willy Tarreau540abe42007-05-02 20:50:16 +02006004 /* zero out remaining args and ensure that at least one entry
6005 * is zeroed out.
6006 */
6007 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006008 args[arg] = line;
6009 }
6010
Willy Tarreau3842f002009-06-14 11:39:52 +02006011 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006012 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006013 char *tmp;
6014
Willy Tarreau3842f002009-06-14 11:39:52 +02006015 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006016 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006017 for (arg=0; *args[arg+1]; arg++)
6018 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006019 *tmp = '\0'; // fix the next arg to \0
6020 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006021 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006022 else if (!strcmp(args[0], "default")) {
6023 kwm = KWM_DEF;
6024 for (arg=0; *args[arg+1]; arg++)
6025 args[arg] = args[arg+1]; // shift args after inversion
6026 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006027
William Lallemand0f99e342011-10-12 17:50:54 +02006028 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6029 strcmp(args[0], "log") != 0) {
6030 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006031 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006032 }
6033
Willy Tarreau977b8e42006-12-29 14:19:17 +01006034 if (!strcmp(args[0], "listen") ||
6035 !strcmp(args[0], "frontend") ||
6036 !strcmp(args[0], "backend") ||
6037 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006038 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006040 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006041 cursection = strdup(args[0]);
6042 }
6043 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006044 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006045 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006046 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006047 }
6048 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006049 confsect = CFG_USERLIST;
6050 free(cursection);
6051 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006052 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006053 else if (!strcmp(args[0], "peers")) {
6054 confsect = CFG_PEERS;
6055 free(cursection);
6056 cursection = strdup(args[0]);
6057 }
6058
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 /* else it's a section keyword */
6060
6061 switch (confsect) {
6062 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006063 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006064 break;
6065 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006066 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006068 case CFG_USERLIST:
6069 err_code |= cfg_parse_users(file, linenum, args, kwm);
6070 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006071 case CFG_PEERS:
6072 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6073 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006074 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006075 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006076 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006078
6079 if (err_code & ERR_ABORT)
6080 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006082 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006083 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006084 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006085 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006086}
6087
Willy Tarreaubb925012009-07-23 13:36:36 +02006088/*
6089 * Returns the error code, 0 if OK, or any combination of :
6090 * - ERR_ABORT: must abort ASAP
6091 * - ERR_FATAL: we can continue parsing but not start the service
6092 * - ERR_WARN: a warning has been emitted
6093 * - ERR_ALERT: an alert has been emitted
6094 * Only the two first ones can stop processing, the two others are just
6095 * indicators.
6096 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006097int check_config_validity()
6098{
6099 int cfgerr = 0;
6100 struct proxy *curproxy = NULL;
6101 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006102 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006103 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006104 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006105 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006106
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006107 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 /*
6109 * Now, check for the integrity of all that we have collected.
6110 */
6111
6112 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006113 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114
Willy Tarreau193b8c62012-11-22 00:17:38 +01006115 if (!global.tune.max_http_hdr)
6116 global.tune.max_http_hdr = MAX_HTTP_HDR;
6117
6118 if (!global.tune.cookie_len)
6119 global.tune.cookie_len = CAPTURE_LEN;
6120
6121 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6122
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006123 /* first, we will invert the proxy list order */
6124 curproxy = NULL;
6125 while (proxy) {
6126 struct proxy *next;
6127
6128 next = proxy->next;
6129 proxy->next = curproxy;
6130 curproxy = proxy;
6131 if (!next)
6132 break;
6133 proxy = next;
6134 }
6135
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006137 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006138 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006139 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006140 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006141 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006142 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006143 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006144
Willy Tarreau050536d2012-10-04 08:47:34 +02006145 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006146 /* proxy ID not set, use automatic numbering with first
6147 * spare entry starting with next_pxid.
6148 */
6149 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6150 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6151 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006152 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006153 next_pxid++;
6154
Willy Tarreau55ea7572007-06-17 19:56:27 +02006155
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006157 /* ensure we don't keep listeners uselessly bound */
6158 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 curproxy = curproxy->next;
6160 continue;
6161 }
6162
Willy Tarreau16a21472012-11-19 12:39:59 +01006163 /* number of processes this proxy is bound to */
6164 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6165
Willy Tarreauff01a212009-03-15 13:46:16 +01006166 switch (curproxy->mode) {
6167 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006169 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006170 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6171 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006172 cfgerr++;
6173 }
6174
6175 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006176 Warning("config : servers will be ignored for %s '%s'.\n",
6177 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006178 break;
6179
6180 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006182 break;
6183
6184 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006185 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006186 break;
6187 }
6188
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006189 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006190 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006191 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006192 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6193 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006194 cfgerr++;
6195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006197 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006198 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6199 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006200 cfgerr++;
6201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006203 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006204 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6205 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006206 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 }
6208 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006209 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006210 /* If no LB algo is set in a backend, and we're not in
6211 * transparent mode, dispatch mode nor proxy mode, we
6212 * want to use balance roundrobin by default.
6213 */
6214 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6215 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
6217 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006218
Willy Tarreau1620ec32011-08-06 17:05:02 +02006219 if (curproxy->options & PR_O_DISPATCH)
6220 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6221 else if (curproxy->options & PR_O_HTTP_PROXY)
6222 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6223 else if (curproxy->options & PR_O_TRANSP)
6224 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006225
Willy Tarreau1620ec32011-08-06 17:05:02 +02006226 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6227 if (curproxy->options & PR_O_DISABLE404) {
6228 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6229 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6230 err_code |= ERR_WARN;
6231 curproxy->options &= ~PR_O_DISABLE404;
6232 }
6233 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6234 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6235 "send-state", proxy_type_str(curproxy), curproxy->id);
6236 err_code |= ERR_WARN;
6237 curproxy->options &= ~PR_O2_CHK_SNDST;
6238 }
Willy Tarreauef781042010-01-27 11:53:01 +01006239 }
6240
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006241 /* if a default backend was specified, let's find it */
6242 if (curproxy->defbe.name) {
6243 struct proxy *target;
6244
Alex Williams96532db2009-11-01 21:27:13 -05006245 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006246 if (!target) {
6247 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6248 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006249 cfgerr++;
6250 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006251 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6252 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006253 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006254 } else {
6255 free(curproxy->defbe.name);
6256 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006257 /* we force the backend to be present on at least all of
6258 * the frontend's processes.
6259 */
6260 target->bind_proc = curproxy->bind_proc ?
6261 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006262
6263 /* Emit a warning if this proxy also has some servers */
6264 if (curproxy->srv) {
6265 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6266 curproxy->id);
6267 err_code |= ERR_WARN;
6268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 }
6270 }
6271
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006272 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006273 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6274 /* map jump target for ACT_SETBE in req_rep chain */
6275 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006276 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006277 struct proxy *target;
6278
Willy Tarreaua496b602006-12-17 23:15:24 +01006279 if (exp->action != ACT_SETBE)
6280 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006281
Alex Williams96532db2009-11-01 21:27:13 -05006282 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006283 if (!target) {
6284 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6285 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006286 cfgerr++;
6287 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006288 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6289 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006290 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006291 } else {
6292 free((void *)exp->replace);
6293 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006294 /* we force the backend to be present on at least all of
6295 * the frontend's processes.
6296 */
6297 target->bind_proc = curproxy->bind_proc ?
6298 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006299 }
6300 }
6301 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006302
6303 /* find the target proxy for 'use_backend' rules */
6304 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006305 struct proxy *target;
6306
Alex Williams96532db2009-11-01 21:27:13 -05006307 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006308
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006309 if (!target) {
6310 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6311 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006312 cfgerr++;
6313 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006314 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6315 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006316 cfgerr++;
6317 } else {
6318 free((void *)rule->be.name);
6319 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006320 /* we force the backend to be present on at least all of
6321 * the frontend's processes.
6322 */
6323 target->bind_proc = curproxy->bind_proc ?
6324 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006325 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006326 }
6327
6328 /* find the target proxy for 'use_backend' rules */
6329 list_for_each_entry(srule, &curproxy->server_rules, list) {
6330 struct server *target = findserver(curproxy, srule->srv.name);
6331
6332 if (!target) {
6333 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6334 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6335 cfgerr++;
6336 continue;
6337 }
6338 free((void *)srule->srv.name);
6339 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006340 }
6341
Emeric Brunb982a3d2010-01-04 15:45:53 +01006342 /* find the target table for 'stick' rules */
6343 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6344 struct proxy *target;
6345
Emeric Brun1d33b292010-01-04 15:47:17 +01006346 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6347 if (mrule->flags & STK_IS_STORE)
6348 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6349
Emeric Brunb982a3d2010-01-04 15:45:53 +01006350 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006351 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006352 else
6353 target = curproxy;
6354
6355 if (!target) {
6356 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6357 curproxy->id, mrule->table.name);
6358 cfgerr++;
6359 }
6360 else if (target->table.size == 0) {
6361 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6362 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6363 cfgerr++;
6364 }
Willy Tarreau12785782012-04-27 21:37:17 +02006365 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6366 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006367 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6368 cfgerr++;
6369 }
6370 else {
6371 free((void *)mrule->table.name);
6372 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006373 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006374 }
6375 }
6376
6377 /* find the target table for 'store response' rules */
6378 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6379 struct proxy *target;
6380
Emeric Brun1d33b292010-01-04 15:47:17 +01006381 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6382
Emeric Brunb982a3d2010-01-04 15:45:53 +01006383 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006384 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006385 else
6386 target = curproxy;
6387
6388 if (!target) {
6389 Alert("Proxy '%s': unable to find store table '%s'.\n",
6390 curproxy->id, mrule->table.name);
6391 cfgerr++;
6392 }
6393 else if (target->table.size == 0) {
6394 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6395 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6396 cfgerr++;
6397 }
Willy Tarreau12785782012-04-27 21:37:17 +02006398 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6399 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006400 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6401 cfgerr++;
6402 }
6403 else {
6404 free((void *)mrule->table.name);
6405 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006406 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006407 }
6408 }
6409
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006410 /* find the target table for 'tcp-request' layer 4 rules */
6411 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6412 struct proxy *target;
6413
Willy Tarreaub4c84932013-07-23 19:15:30 +02006414 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006415 continue;
6416
6417 if (trule->act_prm.trk_ctr.table.n)
6418 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6419 else
6420 target = curproxy;
6421
6422 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006423 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6424 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006425 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006426 cfgerr++;
6427 }
6428 else if (target->table.size == 0) {
6429 Alert("Proxy '%s': table '%s' used but not configured.\n",
6430 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6431 cfgerr++;
6432 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006433 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6434 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6435 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006436 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006437 cfgerr++;
6438 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006439 else {
6440 free(trule->act_prm.trk_ctr.table.n);
6441 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006442 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006443 * to pass a list of counters to track and allocate them right here using
6444 * stktable_alloc_data_type().
6445 */
6446 }
6447 }
6448
Willy Tarreaud1f96522010-08-03 19:34:32 +02006449 /* find the target table for 'tcp-request' layer 6 rules */
6450 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6451 struct proxy *target;
6452
Willy Tarreaub4c84932013-07-23 19:15:30 +02006453 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006454 continue;
6455
6456 if (trule->act_prm.trk_ctr.table.n)
6457 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6458 else
6459 target = curproxy;
6460
6461 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006462 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6463 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006464 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006465 cfgerr++;
6466 }
6467 else if (target->table.size == 0) {
6468 Alert("Proxy '%s': table '%s' used but not configured.\n",
6469 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6470 cfgerr++;
6471 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006472 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6473 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6474 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006475 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006476 cfgerr++;
6477 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006478 else {
6479 free(trule->act_prm.trk_ctr.table.n);
6480 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006481 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006482 * to pass a list of counters to track and allocate them right here using
6483 * stktable_alloc_data_type().
6484 */
6485 }
6486 }
6487
Emeric Brun32da3c42010-09-23 18:39:19 +02006488 if (curproxy->table.peers.name) {
6489 struct peers *curpeers = peers;
6490
6491 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6492 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6493 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006494 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006495 break;
6496 }
6497 }
6498
6499 if (!curpeers) {
6500 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6501 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006502 free((void *)curproxy->table.peers.name);
6503 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006504 cfgerr++;
6505 }
6506 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006507 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6508 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006509 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006510 cfgerr++;
6511 }
6512 }
6513
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006514 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006515 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006516 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6517 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6518 "proxy", curproxy->id);
6519 cfgerr++;
6520 goto out_uri_auth_compat;
6521 }
6522
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006523 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006524 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006525 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006526 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006527
Willy Tarreau95fa4692010-02-01 13:05:50 +01006528 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6529 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006530
6531 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006532 uri_auth_compat_req[i++] = "realm";
6533 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6534 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006535
Willy Tarreau95fa4692010-02-01 13:05:50 +01006536 uri_auth_compat_req[i++] = "unless";
6537 uri_auth_compat_req[i++] = "{";
6538 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6539 uri_auth_compat_req[i++] = "}";
6540 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006541
Willy Tarreauff011f22011-01-06 17:51:27 +01006542 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6543 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006544 cfgerr++;
6545 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006546 }
6547
Willy Tarreauff011f22011-01-06 17:51:27 +01006548 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006549
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006550 if (curproxy->uri_auth->auth_realm) {
6551 free(curproxy->uri_auth->auth_realm);
6552 curproxy->uri_auth->auth_realm = NULL;
6553 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006554
6555 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006556 }
6557out_uri_auth_compat:
6558
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006559 /* compile the log format */
6560 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006561 if (curproxy->conf.logformat_string != default_http_log_format &&
6562 curproxy->conf.logformat_string != default_tcp_log_format &&
6563 curproxy->conf.logformat_string != clf_http_log_format)
6564 free(curproxy->conf.logformat_string);
6565 curproxy->conf.logformat_string = NULL;
6566 free(curproxy->conf.lfs_file);
6567 curproxy->conf.lfs_file = NULL;
6568 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006569 }
6570
Willy Tarreau62a61232013-04-12 18:13:46 +02006571 if (curproxy->conf.logformat_string) {
6572 curproxy->conf.args.ctx = ARGC_LOG;
6573 curproxy->conf.args.file = curproxy->conf.lfs_file;
6574 curproxy->conf.args.line = curproxy->conf.lfs_line;
6575 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006576 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006577 curproxy->conf.args.file = NULL;
6578 curproxy->conf.args.line = 0;
6579 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006580
Willy Tarreau62a61232013-04-12 18:13:46 +02006581 if (curproxy->conf.uniqueid_format_string) {
6582 curproxy->conf.args.ctx = ARGC_UIF;
6583 curproxy->conf.args.file = curproxy->conf.uif_file;
6584 curproxy->conf.args.line = curproxy->conf.uif_line;
6585 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006586 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006587 curproxy->conf.args.file = NULL;
6588 curproxy->conf.args.line = 0;
6589 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006590
6591 /* only now we can check if some args remain unresolved */
6592 cfgerr += smp_resolve_args(curproxy);
6593 if (!cfgerr)
6594 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006595
Willy Tarreau2738a142006-07-08 17:28:09 +02006596 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006597 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006598 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006599 (!curproxy->timeout.connect ||
6600 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006601 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006602 " | While not properly invalid, you will certainly encounter various problems\n"
6603 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006604 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006605 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006606 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006607 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006608
Willy Tarreau1fa31262007-12-03 00:36:16 +01006609 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6610 * We must still support older configurations, so let's find out whether those
6611 * parameters have been set or must be copied from contimeouts.
6612 */
6613 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006614 if (!curproxy->timeout.tarpit ||
6615 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006616 /* tarpit timeout not set. We search in the following order:
6617 * default.tarpit, curr.connect, default.connect.
6618 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006619 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006620 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006621 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006622 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006623 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006624 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006625 }
6626 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006627 (!curproxy->timeout.queue ||
6628 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006629 /* queue timeout not set. We search in the following order:
6630 * default.queue, curr.connect, default.connect.
6631 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006632 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006633 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006634 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006635 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006636 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006637 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006638 }
6639 }
6640
Willy Tarreau1620ec32011-08-06 17:05:02 +02006641 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006642 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6643 curproxy->check_req = (char *)malloc(curproxy->check_len);
6644 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006645 }
6646
Willy Tarreau193b8c62012-11-22 00:17:38 +01006647 /* ensure that cookie capture length is not too large */
6648 if (curproxy->capture_len >= global.tune.cookie_len) {
6649 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6650 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6651 err_code |= ERR_WARN;
6652 curproxy->capture_len = global.tune.cookie_len - 1;
6653 }
6654
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006655 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006656 if (curproxy->nb_req_cap) {
6657 if (curproxy->mode == PR_MODE_HTTP) {
6658 curproxy->req_cap_pool = create_pool("ptrcap",
6659 curproxy->nb_req_cap * sizeof(char *),
6660 MEM_F_SHARED);
6661 } else {
6662 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6663 proxy_type_str(curproxy), curproxy->id);
6664 err_code |= ERR_WARN;
6665 curproxy->to_log &= ~LW_REQHDR;
6666 curproxy->nb_req_cap = 0;
6667 }
6668 }
6669
6670 if (curproxy->nb_rsp_cap) {
6671 if (curproxy->mode == PR_MODE_HTTP) {
6672 curproxy->rsp_cap_pool = create_pool("ptrcap",
6673 curproxy->nb_rsp_cap * sizeof(char *),
6674 MEM_F_SHARED);
6675 } else {
6676 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6677 proxy_type_str(curproxy), curproxy->id);
6678 err_code |= ERR_WARN;
6679 curproxy->to_log &= ~LW_REQHDR;
6680 curproxy->nb_rsp_cap = 0;
6681 }
6682 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006683
Willy Tarreaubaaee002006-06-26 02:48:02 +02006684 /* first, we will invert the servers list order */
6685 newsrv = NULL;
6686 while (curproxy->srv) {
6687 struct server *next;
6688
6689 next = curproxy->srv->next;
6690 curproxy->srv->next = newsrv;
6691 newsrv = curproxy->srv;
6692 if (!next)
6693 break;
6694 curproxy->srv = next;
6695 }
6696
Willy Tarreaudd701652010-05-25 23:03:02 +02006697 /* assign automatic UIDs to servers which don't have one yet */
6698 next_id = 1;
6699 newsrv = curproxy->srv;
6700 while (newsrv != NULL) {
6701 if (!newsrv->puid) {
6702 /* server ID not set, use automatic numbering with first
6703 * spare entry starting with next_svid.
6704 */
6705 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6706 newsrv->conf.id.key = newsrv->puid = next_id;
6707 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6708 }
6709 next_id++;
6710 newsrv = newsrv->next;
6711 }
6712
Willy Tarreau20697042007-11-15 23:26:18 +01006713 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006714 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006715
Willy Tarreau62c3be22012-01-20 13:12:32 +01006716 /*
6717 * If this server supports a maxconn parameter, it needs a dedicated
6718 * tasks to fill the emptied slots when a connection leaves.
6719 * Also, resolve deferred tracking dependency if needed.
6720 */
6721 newsrv = curproxy->srv;
6722 while (newsrv != NULL) {
6723 if (newsrv->minconn > newsrv->maxconn) {
6724 /* Only 'minconn' was specified, or it was higher than or equal
6725 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6726 * this will avoid further useless expensive computations.
6727 */
6728 newsrv->maxconn = newsrv->minconn;
6729 } else if (newsrv->maxconn && !newsrv->minconn) {
6730 /* minconn was not specified, so we set it to maxconn */
6731 newsrv->minconn = newsrv->maxconn;
6732 }
6733
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006734#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006735 if (newsrv->use_ssl || newsrv->check.use_ssl)
6736 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006737#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006738
Willy Tarreau62c3be22012-01-20 13:12:32 +01006739 if (newsrv->trackit) {
6740 struct proxy *px;
6741 struct server *srv;
6742 char *pname, *sname;
6743
6744 pname = newsrv->trackit;
6745 sname = strrchr(pname, '/');
6746
6747 if (sname)
6748 *sname++ = '\0';
6749 else {
6750 sname = pname;
6751 pname = NULL;
6752 }
6753
6754 if (pname) {
6755 px = findproxy(pname, PR_CAP_BE);
6756 if (!px) {
6757 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6758 proxy_type_str(curproxy), curproxy->id,
6759 newsrv->id, pname);
6760 cfgerr++;
6761 goto next_srv;
6762 }
6763 } else
6764 px = curproxy;
6765
6766 srv = findserver(px, sname);
6767 if (!srv) {
6768 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6769 proxy_type_str(curproxy), curproxy->id,
6770 newsrv->id, sname);
6771 cfgerr++;
6772 goto next_srv;
6773 }
6774
6775 if (!(srv->state & SRV_CHECKED)) {
6776 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6777 "tracking as it does not have checks enabled.\n",
6778 proxy_type_str(curproxy), curproxy->id,
6779 newsrv->id, px->id, srv->id);
6780 cfgerr++;
6781 goto next_srv;
6782 }
6783
6784 if (curproxy != px &&
6785 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6786 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6787 "tracking: disable-on-404 option inconsistency.\n",
6788 proxy_type_str(curproxy), curproxy->id,
6789 newsrv->id, px->id, srv->id);
6790 cfgerr++;
6791 goto next_srv;
6792 }
6793
6794 /* if the other server is forced disabled, we have to do the same here */
6795 if (srv->state & SRV_MAINTAIN) {
6796 newsrv->state |= SRV_MAINTAIN;
6797 newsrv->state &= ~SRV_RUNNING;
6798 newsrv->health = 0;
6799 }
6800
6801 newsrv->track = srv;
6802 newsrv->tracknext = srv->tracknext;
6803 srv->tracknext = newsrv;
6804
6805 free(newsrv->trackit);
6806 newsrv->trackit = NULL;
6807 }
6808 next_srv:
6809 newsrv = newsrv->next;
6810 }
6811
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006812 /* We have to initialize the server lookup mechanism depending
6813 * on what LB algorithm was choosen.
6814 */
6815
6816 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6817 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6818 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006819 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6820 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6821 init_server_map(curproxy);
6822 } else {
6823 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6824 fwrr_init_server_groups(curproxy);
6825 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006826 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006827
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006828 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006829 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6830 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6831 fwlc_init_server_tree(curproxy);
6832 } else {
6833 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6834 fas_init_server_tree(curproxy);
6835 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006836 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006837
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006838 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006839 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6840 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6841 chash_init_server_tree(curproxy);
6842 } else {
6843 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6844 init_server_map(curproxy);
6845 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006846 break;
6847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006848
6849 if (curproxy->options & PR_O_LOGASAP)
6850 curproxy->to_log &= ~LW_BYTES;
6851
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006852 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006853 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006854 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6855 proxy_type_str(curproxy), curproxy->id);
6856 err_code |= ERR_WARN;
6857 }
6858
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006859 if (curproxy->mode != PR_MODE_HTTP) {
6860 int optnum;
6861
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006862 if (curproxy->uri_auth) {
6863 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6864 proxy_type_str(curproxy), curproxy->id);
6865 err_code |= ERR_WARN;
6866 curproxy->uri_auth = NULL;
6867 }
6868
Willy Tarreau87cf5142011-08-19 22:57:24 +02006869 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006870 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6871 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6872 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006873 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006874 }
6875
6876 if (curproxy->options & PR_O_ORGTO) {
6877 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6878 "originalto", proxy_type_str(curproxy), curproxy->id);
6879 err_code |= ERR_WARN;
6880 curproxy->options &= ~PR_O_ORGTO;
6881 }
6882
6883 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6884 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6885 (curproxy->cap & cfg_opts[optnum].cap) &&
6886 (curproxy->options & cfg_opts[optnum].val)) {
6887 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6888 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6889 err_code |= ERR_WARN;
6890 curproxy->options &= ~cfg_opts[optnum].val;
6891 }
6892 }
6893
6894 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6895 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6896 (curproxy->cap & cfg_opts2[optnum].cap) &&
6897 (curproxy->options2 & cfg_opts2[optnum].val)) {
6898 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6899 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6900 err_code |= ERR_WARN;
6901 curproxy->options2 &= ~cfg_opts2[optnum].val;
6902 }
6903 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006904
Pieter Baauwd551fb52013-05-08 22:49:23 +02006905#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006906 if (curproxy->conn_src.bind_hdr_occ) {
6907 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006908 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006909 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006910 err_code |= ERR_WARN;
6911 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006912#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006913 }
6914
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006916 * ensure that we're not cross-dressing a TCP server into HTTP.
6917 */
6918 newsrv = curproxy->srv;
6919 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006920 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006921 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6922 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006923 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006924 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006925
Willy Tarreau0cec3312011-10-31 13:49:26 +01006926 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6927 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6928 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6929 err_code |= ERR_WARN;
6930 }
6931
Willy Tarreau82ffa392013-08-13 17:19:08 +02006932 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6933 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6934 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6935 err_code |= ERR_WARN;
6936 }
6937
Pieter Baauwd551fb52013-05-08 22:49:23 +02006938#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006939 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6940 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006941 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 +01006942 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006943 err_code |= ERR_WARN;
6944 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006945#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006946 newsrv = newsrv->next;
6947 }
6948
Willy Tarreauc1a21672009-08-16 22:37:44 +02006949 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006950 if (!curproxy->accept)
6951 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006952
Willy Tarreauc1a21672009-08-16 22:37:44 +02006953 if (curproxy->tcp_req.inspect_delay ||
6954 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006955 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006956
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006957 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006958 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006959 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006960 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006961
6962 /* both TCP and HTTP must check switching rules */
6963 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6964 }
6965
6966 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006967 if (curproxy->tcp_req.inspect_delay ||
6968 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6969 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6970
Emeric Brun97679e72010-09-23 17:56:44 +02006971 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6972 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6973
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006974 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006975 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006976 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006977 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006978
6979 /* If the backend does requires RDP cookie persistence, we have to
6980 * enable the corresponding analyser.
6981 */
6982 if (curproxy->options2 & PR_O2_RDPC_PRST)
6983 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6984 }
6985
Emeric Brunc52962f2012-11-15 18:28:02 +01006986#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006987 /* Configure SSL for each bind line.
6988 * Note: if configuration fails at some point, the ->ctx member
6989 * remains NULL so that listeners can later detach.
6990 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006991 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006992 if (!bind_conf->is_ssl) {
6993 if (bind_conf->default_ctx) {
6994 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6995 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6996 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006997 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006998 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006999 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007000 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007001 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007002 cfgerr++;
7003 continue;
7004 }
7005
Emeric Brun4b3091e2012-09-24 15:48:52 +02007006 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007007 Alert("Unable to allocate SSL session cache.\n");
7008 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007009 continue;
7010 }
7011
Emeric Brunfc0421f2012-09-07 17:30:07 +02007012 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007013 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007014 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007015#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007016
Willy Tarreaue6b98942007-10-29 01:09:36 +01007017 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007018 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007019 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007020 if (!listener->luid) {
7021 /* listener ID not set, use automatic numbering with first
7022 * spare entry starting with next_luid.
7023 */
7024 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7025 listener->conf.id.key = listener->luid = next_id;
7026 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007027 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007028 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007029
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007030 /* enable separate counters */
7031 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7032 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007033 if (!listener->name)
7034 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007035 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007036
Willy Tarreaue6b98942007-10-29 01:09:36 +01007037 if (curproxy->options & PR_O_TCP_NOLING)
7038 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007039 if (!listener->maxconn)
7040 listener->maxconn = curproxy->maxconn;
7041 if (!listener->backlog)
7042 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007043 if (!listener->maxaccept)
7044 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7045
7046 /* we want to have an optimal behaviour on single process mode to
7047 * maximize the work at once, but in multi-process we want to keep
7048 * some fairness between processes, so we target half of the max
7049 * number of events to be balanced over all the processes the proxy
7050 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7051 * used to disable the limit.
7052 */
7053 if (listener->maxaccept > 0) {
7054 if (nbproc > 1)
7055 listener->maxaccept = (listener->maxaccept + 1) / 2;
7056 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7057 }
7058
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007059 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007060 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007061 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007062 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007063
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007064 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7065 listener->options |= LI_O_TCP_RULES;
7066
Willy Tarreaude3041d2010-05-31 10:56:17 +02007067 if (curproxy->mon_mask.s_addr)
7068 listener->options |= LI_O_CHK_MONNET;
7069
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007070 /* smart accept mode is automatic in HTTP mode */
7071 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007072 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007073 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7074 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007075 }
7076
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007077 /* Release unused SSL configs */
7078 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7079 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007080 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007081#ifdef USE_OPENSSL
7082 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007083 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007084 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007085 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007086 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007087#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007088 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007089
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007090 /* Check multi-process mode compatibility for the current proxy */
7091 if (global.nbproc > 1) {
7092 int nbproc = 0;
7093 if (curproxy->bind_proc) {
7094 int proc;
7095 for (proc = 0; proc < global.nbproc; proc++) {
7096 if (curproxy->bind_proc & (1 << proc)) {
7097 nbproc++;
7098 }
7099 }
7100 } else {
7101 nbproc = global.nbproc;
7102 }
7103 if (curproxy->table.peers.name) {
7104 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7105 curproxy->id);
7106 cfgerr++;
7107 }
7108 if (nbproc > 1) {
7109 if (curproxy->uri_auth) {
7110 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7111 curproxy->id);
7112 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7113 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7114 curproxy->id);
7115 }
7116 }
7117 if (curproxy->appsession_name) {
7118 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7119 curproxy->id);
7120 }
7121 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7122 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7123 curproxy->id);
7124 }
7125 }
7126 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007127
7128 /* create the task associated with the proxy */
7129 curproxy->task = task_new();
7130 if (curproxy->task) {
7131 curproxy->task->context = curproxy;
7132 curproxy->task->process = manage_proxy;
7133 /* no need to queue, it will be done automatically if some
7134 * listener gets limited.
7135 */
7136 curproxy->task->expire = TICK_ETERNITY;
7137 } else {
7138 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7139 curproxy->id);
7140 cfgerr++;
7141 }
7142
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143 curproxy = curproxy->next;
7144 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007145
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007146 /* Check multi-process mode compatibility */
7147 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007148 if (global.stats_fe && !global.stats_fe->bind_proc) {
7149 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 +01007150 }
7151 }
7152
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007153 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7154 struct auth_users *curuser;
7155 int g;
7156
7157 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7158 unsigned int group_mask = 0;
7159 char *group = NULL;
7160
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007161 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007162 continue;
7163
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007164 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007165
7166 for (g = 0; g < curuserlist->grpcnt; g++)
7167 if (!strcmp(curuserlist->groups[g], group))
7168 break;
7169
7170 if (g == curuserlist->grpcnt) {
7171 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7172 curuserlist->name, group, curuser->user);
7173 err_code |= ERR_ALERT | ERR_FATAL;
7174 goto out;
7175 }
7176
7177 group_mask |= (1 << g);
7178 }
7179
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007180 free(curuser->u.groups);
7181 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007182 }
7183
7184 for (g = 0; g < curuserlist->grpcnt; g++) {
7185 char *user = NULL;
7186
7187 if (!curuserlist->groupusers[g])
7188 continue;
7189
7190 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7191 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7192 if (!strcmp(curuser->user, user))
7193 break;
7194
7195 if (!curuser) {
7196 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7197 curuserlist->name, user, curuserlist->groups[g]);
7198 err_code |= ERR_ALERT | ERR_FATAL;
7199 goto out;
7200 }
7201
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007202 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007203 }
7204
7205 free(curuserlist->groupusers[g]);
7206 }
7207
7208 free(curuserlist->groupusers);
7209
7210#ifdef DEBUG_AUTH
7211 for (g = 0; g < curuserlist->grpcnt; g++) {
7212 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7213
7214 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007215 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007216 fprintf(stderr, " %s", curuser->user);
7217 }
7218
7219 fprintf(stderr, "\n");
7220 }
7221#endif
7222
Willy Tarreaufbb78422011-06-05 15:38:35 +02007223 }
7224
7225 /* automatically compute fullconn if not set. We must not do it in the
7226 * loop above because cross-references are not yet fully resolved.
7227 */
7228 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7229 /* If <fullconn> is not set, let's set it to 10% of the sum of
7230 * the possible incoming frontend's maxconns.
7231 */
7232 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7233 struct proxy *fe;
7234 int total = 0;
7235
7236 /* sum up the number of maxconns of frontends which
7237 * reference this backend at least once or which are
7238 * the same one ('listen').
7239 */
7240 for (fe = proxy; fe; fe = fe->next) {
7241 struct switching_rule *rule;
7242 struct hdr_exp *exp;
7243 int found = 0;
7244
7245 if (!(fe->cap & PR_CAP_FE))
7246 continue;
7247
7248 if (fe == curproxy) /* we're on a "listen" instance */
7249 found = 1;
7250
7251 if (fe->defbe.be == curproxy) /* "default_backend" */
7252 found = 1;
7253
7254 /* check if a "use_backend" rule matches */
7255 if (!found) {
7256 list_for_each_entry(rule, &fe->switching_rules, list) {
7257 if (rule->be.backend == curproxy) {
7258 found = 1;
7259 break;
7260 }
7261 }
7262 }
7263
7264 /* check if a "reqsetbe" rule matches */
7265 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7266 if (exp->action == ACT_SETBE &&
7267 (struct proxy *)exp->replace == curproxy) {
7268 found = 1;
7269 break;
7270 }
7271 }
7272
7273 /* now we've checked all possible ways to reference a backend
7274 * from a frontend.
7275 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007276 if (!found)
7277 continue;
7278 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007279 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007280 /* we have the sum of the maxconns in <total>. We only
7281 * keep 10% of that sum to set the default fullconn, with
7282 * a hard minimum of 1 (to avoid a divide by zero).
7283 */
7284 curproxy->fullconn = (total + 9) / 10;
7285 if (!curproxy->fullconn)
7286 curproxy->fullconn = 1;
7287 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007288 }
7289
Willy Tarreau056f5682010-06-06 15:51:11 +02007290 /* initialize stick-tables on backend capable proxies. This must not
7291 * be done earlier because the data size may be discovered while parsing
7292 * other proxies.
7293 */
7294 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007295 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007296
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007297 /*
7298 * Recount currently required checks.
7299 */
7300
7301 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7302 int optnum;
7303
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007304 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7305 if (curproxy->options & cfg_opts[optnum].val)
7306 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007307
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007308 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7309 if (curproxy->options2 & cfg_opts2[optnum].val)
7310 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007311 }
7312
Willy Tarreau122541c2011-09-07 21:24:49 +02007313 if (peers) {
7314 struct peers *curpeers = peers, **last;
7315 struct peer *p, *pb;
7316
7317 /* Remove all peers sections which don't have a valid listener.
7318 * This can happen when a peers section is never referenced and
7319 * does not contain a local peer.
7320 */
7321 last = &peers;
7322 while (*last) {
7323 curpeers = *last;
7324 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007325 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007326 last = &curpeers->next;
7327 continue;
7328 }
7329
7330 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7331 curpeers->id, localpeer);
7332
7333 p = curpeers->remote;
7334 while (p) {
7335 pb = p->next;
7336 free(p->id);
7337 free(p);
7338 p = pb;
7339 }
7340
7341 /* Destroy and unlink this curpeers section.
7342 * Note: curpeers is backed up into *last.
7343 */
7344 free(curpeers->id);
7345 curpeers = curpeers->next;
7346 free(*last);
7347 *last = curpeers;
7348 }
7349 }
7350
Willy Tarreau34eb6712011-10-24 18:15:04 +02007351 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007352 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007353 MEM_F_SHARED);
7354
Willy Tarreaubb925012009-07-23 13:36:36 +02007355 if (cfgerr > 0)
7356 err_code |= ERR_ALERT | ERR_FATAL;
7357 out:
7358 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007359}
7360
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007361/*
7362 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7363 * parsing sessions.
7364 */
7365void cfg_register_keywords(struct cfg_kw_list *kwl)
7366{
7367 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7368}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007369
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007370/*
7371 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7372 */
7373void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7374{
7375 LIST_DEL(&kwl->list);
7376 LIST_INIT(&kwl->list);
7377}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007378
7379/*
7380 * Local variables:
7381 * c-indent-level: 8
7382 * c-basic-offset: 8
7383 * End:
7384 */