blob: 539c4eccadfbd6c841c6ab77f653f24c36bf455e [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 Horman66183002013-02-23 10:16:43 +09004905 newsrv->check.server = newsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 newsrv->state |= SRV_CHECKED;
4907 }
4908
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004909 if (!defsrv) {
4910 if (newsrv->state & SRV_BACKUP)
4911 curproxy->srv_bck++;
4912 else
4913 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004914
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004915 newsrv->prev_state = newsrv->state;
4916 }
William Lallemanda73203e2012-03-12 12:48:57 +01004917 }
4918
4919 else if (strcmp(args[0], "unique-id-format") == 0) {
4920 if (!*(args[1])) {
4921 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
4924 }
William Lallemand3203ff42012-11-11 17:30:56 +01004925 if (*(args[2])) {
4926 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004930 free(curproxy->conf.uniqueid_format_string);
4931 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004932
Willy Tarreau62a61232013-04-12 18:13:46 +02004933 free(curproxy->conf.uif_file);
4934 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4935 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004936 }
William Lallemanda73203e2012-03-12 12:48:57 +01004937
4938 else if (strcmp(args[0], "unique-id-header") == 0) {
4939 if (!*(args[1])) {
4940 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
4943 }
4944 free(curproxy->header_unique_id);
4945 curproxy->header_unique_id = strdup(args[1]);
4946 }
4947
William Lallemand723b73a2012-02-08 16:37:49 +01004948 else if (strcmp(args[0], "log-format") == 0) {
4949 if (!*(args[1])) {
4950 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953 }
William Lallemand3203ff42012-11-11 17:30:56 +01004954 if (*(args[2])) {
4955 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
4958 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004959
Willy Tarreau62a61232013-04-12 18:13:46 +02004960 if (curproxy->conf.logformat_string != default_http_log_format &&
4961 curproxy->conf.logformat_string != default_tcp_log_format &&
4962 curproxy->conf.logformat_string != clf_http_log_format)
4963 free(curproxy->conf.logformat_string);
4964 curproxy->conf.logformat_string = strdup(args[1]);
4965
4966 free(curproxy->conf.lfs_file);
4967 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4968 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004969
4970 /* get a chance to improve log-format error reporting by
4971 * reporting the correct line-number when possible.
4972 */
4973 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4974 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4975 file, linenum, curproxy->id);
4976 err_code |= ERR_WARN;
4977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
William Lallemand723b73a2012-02-08 16:37:49 +01004979
William Lallemand0f99e342011-10-12 17:50:54 +02004980 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4981 /* delete previous herited or defined syslog servers */
4982 struct logsrv *back;
4983
4984 if (*(args[1]) != 0) {
4985 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989
William Lallemand723b73a2012-02-08 16:37:49 +01004990 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4991 LIST_DEL(&tmplogsrv->list);
4992 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004993 }
4994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004996 struct logsrv *logsrv;
4997
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004999 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005000 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005001 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005002 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005003 LIST_INIT(&node->list);
5004 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006 }
5007 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005008 struct sockaddr_storage *sk;
5009 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005010
5011 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012
William Lallemand0f99e342011-10-12 17:50:54 +02005013 logsrv->facility = get_log_facility(args[2]);
5014 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
5018
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
5020
William Lallemand0f99e342011-10-12 17:50:54 +02005021 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005023 logsrv->level = get_log_level(args[3]);
5024 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
5028
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 }
5030 }
5031
William Lallemand0f99e342011-10-12 17:50:54 +02005032 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005033 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005034 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005035 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005036 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005040 }
5041 }
5042
Willy Tarreau902636f2013-03-10 19:44:48 +01005043 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005044 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005045 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005047 goto out;
5048 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005049
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005050 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005051
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005052 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005053 if (port1 != port2) {
5054 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5055 file, linenum, args[0], args[1]);
5056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
5058 }
5059
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005060 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005061 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 }
William Lallemand0f99e342011-10-12 17:50:54 +02005063
5064 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 }
5066 else {
5067 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5068 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 }
5073 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005074 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005075 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005076 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005077 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005078
Willy Tarreau977b8e42006-12-29 14:19:17 +01005079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005081
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005083 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5084 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005088
5089 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005090 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5091 free(curproxy->conn_src.iface_name);
5092 curproxy->conn_src.iface_name = NULL;
5093 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005094
Willy Tarreau902636f2013-03-10 19:44:48 +01005095 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005096 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005097 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005098 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005100 goto out;
5101 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005102
5103 proto = protocol_by_family(sk->ss_family);
5104 if (!proto || !proto->connect) {
5105 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005106 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005110
5111 if (port1 != port2) {
5112 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5113 file, linenum, args[0], args[1]);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
5117
Willy Tarreauef9a3602012-12-08 22:29:20 +01005118 curproxy->conn_src.source_addr = *sk;
5119 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005120
5121 cur_arg = 2;
5122 while (*(args[cur_arg])) {
5123 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005124#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5125#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005126 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005127 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5128 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005131 }
5132#endif
5133 if (!*args[cur_arg + 1]) {
5134 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5135 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005138 }
5139
5140 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005141 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5142 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005143 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005144 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5145 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005146 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5147 char *name, *end;
5148
5149 name = args[cur_arg+1] + 7;
5150 while (isspace(*name))
5151 name++;
5152
5153 end = name;
5154 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5155 end++;
5156
Willy Tarreauef9a3602012-12-08 22:29:20 +01005157 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5158 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5159 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5160 curproxy->conn_src.bind_hdr_len = end - name;
5161 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5162 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5163 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005164
5165 /* now look for an occurrence number */
5166 while (isspace(*end))
5167 end++;
5168 if (*end == ',') {
5169 end++;
5170 name = end;
5171 if (*end == '-')
5172 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005173 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005174 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005175 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005176 }
5177
Willy Tarreauef9a3602012-12-08 22:29:20 +01005178 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005179 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5180 " occurrences values smaller than %d.\n",
5181 file, linenum, MAX_HDR_HISTORY);
5182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005185 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005186 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005187
Willy Tarreau902636f2013-03-10 19:44:48 +01005188 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005189 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005190 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005191 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005193 goto out;
5194 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005195
5196 proto = protocol_by_family(sk->ss_family);
5197 if (!proto || !proto->connect) {
5198 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5199 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005203
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005204 if (port1 != port2) {
5205 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5206 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005210 curproxy->conn_src.tproxy_addr = *sk;
5211 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005212 }
5213 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005214#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005215 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005216#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005217#else /* no TPROXY support */
5218 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005219 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005222#endif
5223 cur_arg += 2;
5224 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005225 }
5226
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005227 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5228#ifdef SO_BINDTODEVICE
5229 if (!*args[cur_arg + 1]) {
5230 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005234 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005235 free(curproxy->conn_src.iface_name);
5236 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5237 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005238 global.last_checks |= LSTCHK_NETADM;
5239#else
5240 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5241 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005244#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005245 cur_arg += 2;
5246 continue;
5247 }
5248 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005249 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005254 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5255 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5256 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5263 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267
5268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005269 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005270 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
5274 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005276 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
5281 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005283 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005284 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
5288 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005290 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 }
5295 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005297 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005298 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005299 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005302 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005304 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005305 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005307 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005308 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005309 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005311 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005312 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005314 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005315 }
5316 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005318 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005319 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005321 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5326 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005330
5331 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005332 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005333 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005334 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 }
5337 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005339 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005340 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005341 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 }
5344 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005346 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005347 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005348 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005352 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005353 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005354 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005355 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
5358 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005359 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005360 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005361 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005365 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005366 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005367 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005368 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005370 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005373 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005374
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 if (curproxy == &defproxy) {
5376 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005380 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 if (*(args[1]) == 0) {
5384 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005388
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005389 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005390 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5391 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5392 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005396 err_code |= warnif_cond_conflicts(cond,
5397 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5398 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005399 }
5400 else if (*args[2]) {
5401 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5402 file, linenum, args[0], args[2]);
5403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
5406
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005407 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005408 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005409 wl->s = strdup(args[1]);
5410 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005411 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
5413 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005414 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5416 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005420
Willy Tarreauade5ec42010-01-28 19:33:49 +01005421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005422 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005423 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 }
5427 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005429 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005436 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 }
5441 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005442 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005443 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 }
5448
Willy Tarreauade5ec42010-01-28 19:33:49 +01005449 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005450 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005451 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005452 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 }
5455 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005456 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005457 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005458 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005459 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
5462 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005464 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005465 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 }
5469 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005470 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005471
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 if (curproxy == &defproxy) {
5473 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005477 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 if (*(args[1]) == 0) {
5481 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 }
5485
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005486 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005487 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5488 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5489 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005493 err_code |= warnif_cond_conflicts(cond,
5494 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5495 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005496 }
5497 else if (*args[2]) {
5498 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5499 file, linenum, args[0], args[2]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005504 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005505 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005506 wl->s = strdup(args[1]);
5507 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 }
5509 else if (!strcmp(args[0], "errorloc") ||
5510 !strcmp(args[0], "errorloc302") ||
5511 !strcmp(args[0], "errorloc303")) { /* error location */
5512 int errnum, errlen;
5513 char *err;
5514
Willy Tarreau977b8e42006-12-29 14:19:17 +01005515 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005516 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005517
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005519 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 }
5523
5524 errnum = atol(args[1]);
5525 if (!strcmp(args[0], "errorloc303")) {
5526 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5527 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5528 } else {
5529 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5530 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5531 }
5532
Willy Tarreau0f772532006-12-23 20:51:41 +01005533 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5534 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005535 chunk_destroy(&curproxy->errmsg[rc]);
5536 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005537 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005540
5541 if (rc >= HTTP_ERR_SIZE) {
5542 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5543 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 free(err);
5545 }
5546 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005547 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5548 int errnum, errlen, fd;
5549 char *err;
5550 struct stat stat;
5551
5552 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005553 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005554
5555 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005556 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005559 }
5560
5561 fd = open(args[2], O_RDONLY);
5562 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5563 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5564 file, linenum, args[2], args[1]);
5565 if (fd >= 0)
5566 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005569 }
5570
Willy Tarreau27a674e2009-08-17 07:23:33 +02005571 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005572 errlen = stat.st_size;
5573 } else {
5574 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005575 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005576 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005577 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005578 }
5579
5580 err = malloc(errlen); /* malloc() must succeed during parsing */
5581 errnum = read(fd, err, errlen);
5582 if (errnum != errlen) {
5583 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5584 file, linenum, args[2], args[1]);
5585 close(fd);
5586 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005589 }
5590 close(fd);
5591
5592 errnum = atol(args[1]);
5593 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5594 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005595 chunk_destroy(&curproxy->errmsg[rc]);
5596 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005597 break;
5598 }
5599 }
5600
5601 if (rc >= HTTP_ERR_SIZE) {
5602 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5603 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005604 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005605 free(err);
5606 }
5607 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005608 else if (!strcmp(args[0], "compression")) {
5609 struct comp *comp;
5610 if (curproxy->comp == NULL) {
5611 comp = calloc(1, sizeof(struct comp));
5612 curproxy->comp = comp;
5613 } else {
5614 comp = curproxy->comp;
5615 }
5616
5617 if (!strcmp(args[1], "algo")) {
5618 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005619 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005620
William Lallemand82fe75c2012-10-23 10:25:10 +02005621 cur_arg = 2;
5622 if (!*args[cur_arg]) {
5623 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5624 file, linenum, args[0]);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628 while (*(args[cur_arg])) {
5629 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5630 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5631 file, linenum, args[0], args[cur_arg]);
5632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
William Lallemand552df672012-11-07 13:21:47 +01005635 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5636 curproxy->comp->algos->end(&ctx);
5637 } else {
5638 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5639 file, linenum, args[0], args[cur_arg]);
5640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005643 cur_arg ++;
5644 continue;
5645 }
5646 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005647 else if (!strcmp(args[1], "offload")) {
5648 comp->offload = 1;
5649 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005650 else if (!strcmp(args[1], "type")) {
5651 int cur_arg;
5652 cur_arg = 2;
5653 if (!*args[cur_arg]) {
5654 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5655 file, linenum, args[0]);
5656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659 while (*(args[cur_arg])) {
5660 comp_append_type(comp, args[cur_arg]);
5661 cur_arg ++;
5662 continue;
5663 }
5664 }
5665 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005666 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005667 file, linenum, args[0]);
5668 err_code |= ERR_ALERT | ERR_FATAL;
5669 goto out;
5670 }
5671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005673 struct cfg_kw_list *kwl;
5674 int index;
5675
5676 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5677 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5678 if (kwl->kw[index].section != CFG_LISTEN)
5679 continue;
5680 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5681 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005682 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005683 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005684 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005685 err_code |= ERR_ALERT | ERR_FATAL;
5686 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005687 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005688 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005689 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= ERR_WARN;
5691 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005692 }
Willy Tarreau93893792009-07-23 13:19:11 +02005693 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005694 }
5695 }
5696 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005697
Willy Tarreau6daf3432008-01-22 16:44:08 +01005698 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 }
Willy Tarreau93893792009-07-23 13:19:11 +02005702 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005703 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005704 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705}
5706
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005707int
5708cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5709{
5710
5711 int err_code = 0;
5712 const char *err;
5713
5714 if (!strcmp(args[0], "userlist")) { /* new userlist */
5715 struct userlist *newul;
5716
5717 if (!*args[1]) {
5718 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5719 file, linenum, args[0]);
5720 err_code |= ERR_ALERT | ERR_FATAL;
5721 goto out;
5722 }
5723
5724 err = invalid_char(args[1]);
5725 if (err) {
5726 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5727 file, linenum, *err, args[0], args[1]);
5728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
5730 }
5731
5732 for (newul = userlist; newul; newul = newul->next)
5733 if (!strcmp(newul->name, args[1])) {
5734 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5735 file, linenum, args[1]);
5736 err_code |= ERR_WARN;
5737 goto out;
5738 }
5739
5740 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5741 if (!newul) {
5742 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5743 err_code |= ERR_ALERT | ERR_ABORT;
5744 goto out;
5745 }
5746
5747 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5748 newul->name = strdup(args[1]);
5749
5750 if (!newul->groupusers | !newul->name) {
5751 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5752 err_code |= ERR_ALERT | ERR_ABORT;
5753 goto out;
5754 }
5755
5756 newul->next = userlist;
5757 userlist = newul;
5758
5759 } else if (!strcmp(args[0], "group")) { /* new group */
5760 int cur_arg, i;
5761 const char *err;
5762
5763 if (!*args[1]) {
5764 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5765 file, linenum, args[0]);
5766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
5768 }
5769
5770 err = invalid_char(args[1]);
5771 if (err) {
5772 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5773 file, linenum, *err, args[0], args[1]);
5774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
5776 }
5777
5778 for(i = 0; i < userlist->grpcnt; i++)
5779 if (!strcmp(userlist->groups[i], args[1])) {
5780 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5781 file, linenum, args[1], userlist->name);
5782 err_code |= ERR_ALERT;
5783 goto out;
5784 }
5785
5786 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5787 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5788 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5789 err_code |= ERR_ALERT | ERR_FATAL;
5790 goto out;
5791 }
5792
5793 cur_arg = 2;
5794
5795 while (*args[cur_arg]) {
5796 if (!strcmp(args[cur_arg], "users")) {
5797 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5798 cur_arg += 2;
5799 continue;
5800 } else {
5801 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5802 file, linenum, args[0]);
5803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805 }
5806 }
5807
5808 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5809 } else if (!strcmp(args[0], "user")) { /* new user */
5810 struct auth_users *newuser;
5811 int cur_arg;
5812
5813 if (!*args[1]) {
5814 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5815 file, linenum, args[0]);
5816 err_code |= ERR_ALERT | ERR_FATAL;
5817 goto out;
5818 }
5819
5820 for (newuser = userlist->users; newuser; newuser = newuser->next)
5821 if (!strcmp(newuser->user, args[1])) {
5822 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5823 file, linenum, args[1], userlist->name);
5824 err_code |= ERR_ALERT;
5825 goto out;
5826 }
5827
5828 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5829 if (!newuser) {
5830 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5831 err_code |= ERR_ALERT | ERR_ABORT;
5832 goto out;
5833 }
5834
5835 newuser->user = strdup(args[1]);
5836
5837 newuser->next = userlist->users;
5838 userlist->users = newuser;
5839
5840 cur_arg = 2;
5841
5842 while (*args[cur_arg]) {
5843 if (!strcmp(args[cur_arg], "password")) {
5844#ifndef CONFIG_HAP_CRYPT
5845 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5846 file, linenum);
5847 err_code |= ERR_ALERT;
5848#endif
5849 newuser->pass = strdup(args[cur_arg + 1]);
5850 cur_arg += 2;
5851 continue;
5852 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5853 newuser->pass = strdup(args[cur_arg + 1]);
5854 newuser->flags |= AU_O_INSECURE;
5855 cur_arg += 2;
5856 continue;
5857 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005858 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005859 cur_arg += 2;
5860 continue;
5861 } else {
5862 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5863 file, linenum, args[0]);
5864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866 }
5867 }
5868 } else {
5869 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5870 err_code |= ERR_ALERT | ERR_FATAL;
5871 }
5872
5873out:
5874 return err_code;
5875}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876
5877/*
5878 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005879 * Returns the error code, 0 if OK, or any combination of :
5880 * - ERR_ABORT: must abort ASAP
5881 * - ERR_FATAL: we can continue parsing but not start the service
5882 * - ERR_WARN: a warning has been emitted
5883 * - ERR_ALERT: an alert has been emitted
5884 * Only the two first ones can stop processing, the two others are just
5885 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005887int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005889 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005890 FILE *f;
5891 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005893 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 if ((f=fopen(file,"r")) == NULL)
5896 return -1;
5897
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005898 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005899 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005900 char *end;
5901 char *args[MAX_LINE_ARGS + 1];
5902 char *line = thisline;
5903
Willy Tarreaubaaee002006-06-26 02:48:02 +02005904 linenum++;
5905
5906 end = line + strlen(line);
5907
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005908 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5909 /* Check if we reached the limit and the last char is not \n.
5910 * Watch out for the last line without the terminating '\n'!
5911 */
5912 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005913 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005915 }
5916
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005918 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 line++;
5920
5921 arg = 0;
5922 args[arg] = line;
5923
5924 while (*line && arg < MAX_LINE_ARGS) {
5925 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5926 * C equivalent value. Other combinations left unchanged (eg: \1).
5927 */
5928 if (*line == '\\') {
5929 int skip = 0;
5930 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5931 *line = line[1];
5932 skip = 1;
5933 }
5934 else if (line[1] == 'r') {
5935 *line = '\r';
5936 skip = 1;
5937 }
5938 else if (line[1] == 'n') {
5939 *line = '\n';
5940 skip = 1;
5941 }
5942 else if (line[1] == 't') {
5943 *line = '\t';
5944 skip = 1;
5945 }
5946 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005947 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 unsigned char hex1, hex2;
5949 hex1 = toupper(line[2]) - '0';
5950 hex2 = toupper(line[3]) - '0';
5951 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5952 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5953 *line = (hex1<<4) + hex2;
5954 skip = 3;
5955 }
5956 else {
5957 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 }
5960 }
5961 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005962 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 end -= skip;
5964 }
5965 line++;
5966 }
5967 else if (*line == '#' || *line == '\n' || *line == '\r') {
5968 /* end of string, end of loop */
5969 *line = 0;
5970 break;
5971 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005972 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005974 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005975 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 line++;
5977 args[++arg] = line;
5978 }
5979 else {
5980 line++;
5981 }
5982 }
5983
5984 /* empty line */
5985 if (!**args)
5986 continue;
5987
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005988 if (*line) {
5989 /* we had to stop due to too many args.
5990 * Let's terminate the string, print the offending part then cut the
5991 * last arg.
5992 */
5993 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5994 line++;
5995 *line = '\0';
5996
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005997 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005998 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005999 err_code |= ERR_ALERT | ERR_FATAL;
6000 args[arg] = line;
6001 }
6002
Willy Tarreau540abe42007-05-02 20:50:16 +02006003 /* zero out remaining args and ensure that at least one entry
6004 * is zeroed out.
6005 */
6006 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007 args[arg] = line;
6008 }
6009
Willy Tarreau3842f002009-06-14 11:39:52 +02006010 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006011 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006012 char *tmp;
6013
Willy Tarreau3842f002009-06-14 11:39:52 +02006014 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006015 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006016 for (arg=0; *args[arg+1]; arg++)
6017 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006018 *tmp = '\0'; // fix the next arg to \0
6019 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006020 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006021 else if (!strcmp(args[0], "default")) {
6022 kwm = KWM_DEF;
6023 for (arg=0; *args[arg+1]; arg++)
6024 args[arg] = args[arg+1]; // shift args after inversion
6025 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006026
William Lallemand0f99e342011-10-12 17:50:54 +02006027 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6028 strcmp(args[0], "log") != 0) {
6029 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006030 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006031 }
6032
Willy Tarreau977b8e42006-12-29 14:19:17 +01006033 if (!strcmp(args[0], "listen") ||
6034 !strcmp(args[0], "frontend") ||
6035 !strcmp(args[0], "backend") ||
6036 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006037 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006039 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006040 cursection = strdup(args[0]);
6041 }
6042 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006044 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006045 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006046 }
6047 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006048 confsect = CFG_USERLIST;
6049 free(cursection);
6050 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006051 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006052 else if (!strcmp(args[0], "peers")) {
6053 confsect = CFG_PEERS;
6054 free(cursection);
6055 cursection = strdup(args[0]);
6056 }
6057
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058 /* else it's a section keyword */
6059
6060 switch (confsect) {
6061 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006062 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 break;
6064 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006065 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006066 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006067 case CFG_USERLIST:
6068 err_code |= cfg_parse_users(file, linenum, args, kwm);
6069 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006070 case CFG_PEERS:
6071 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6072 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006073 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006074 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006075 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006076 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006077
6078 if (err_code & ERR_ABORT)
6079 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006080 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006081 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006082 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006084 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006085}
6086
Willy Tarreaubb925012009-07-23 13:36:36 +02006087/*
6088 * Returns the error code, 0 if OK, or any combination of :
6089 * - ERR_ABORT: must abort ASAP
6090 * - ERR_FATAL: we can continue parsing but not start the service
6091 * - ERR_WARN: a warning has been emitted
6092 * - ERR_ALERT: an alert has been emitted
6093 * Only the two first ones can stop processing, the two others are just
6094 * indicators.
6095 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006096int check_config_validity()
6097{
6098 int cfgerr = 0;
6099 struct proxy *curproxy = NULL;
6100 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006101 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006102 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006103 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006104 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006106 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006107 /*
6108 * Now, check for the integrity of all that we have collected.
6109 */
6110
6111 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006112 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113
Willy Tarreau193b8c62012-11-22 00:17:38 +01006114 if (!global.tune.max_http_hdr)
6115 global.tune.max_http_hdr = MAX_HTTP_HDR;
6116
6117 if (!global.tune.cookie_len)
6118 global.tune.cookie_len = CAPTURE_LEN;
6119
6120 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6121
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006122 /* first, we will invert the proxy list order */
6123 curproxy = NULL;
6124 while (proxy) {
6125 struct proxy *next;
6126
6127 next = proxy->next;
6128 proxy->next = curproxy;
6129 curproxy = proxy;
6130 if (!next)
6131 break;
6132 proxy = next;
6133 }
6134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006136 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006137 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006138 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006139 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006140 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006141 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006142 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006143
Willy Tarreau050536d2012-10-04 08:47:34 +02006144 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006145 /* proxy ID not set, use automatic numbering with first
6146 * spare entry starting with next_pxid.
6147 */
6148 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6149 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6150 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006151 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006152 next_pxid++;
6153
Willy Tarreau55ea7572007-06-17 19:56:27 +02006154
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006156 /* ensure we don't keep listeners uselessly bound */
6157 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 curproxy = curproxy->next;
6159 continue;
6160 }
6161
Willy Tarreau16a21472012-11-19 12:39:59 +01006162 /* number of processes this proxy is bound to */
6163 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6164
Willy Tarreauff01a212009-03-15 13:46:16 +01006165 switch (curproxy->mode) {
6166 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006167 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006168 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006169 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6170 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006171 cfgerr++;
6172 }
6173
6174 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006175 Warning("config : servers will be ignored for %s '%s'.\n",
6176 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006177 break;
6178
6179 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006180 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006181 break;
6182
6183 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006184 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006185 break;
6186 }
6187
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006188 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006189 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006190 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006191 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6192 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006193 cfgerr++;
6194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006196 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006197 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6198 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006199 cfgerr++;
6200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006202 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6204 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006205 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006206 }
6207 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006208 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006209 /* If no LB algo is set in a backend, and we're not in
6210 * transparent mode, dispatch mode nor proxy mode, we
6211 * want to use balance roundrobin by default.
6212 */
6213 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6214 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 }
6216 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006217
Willy Tarreau1620ec32011-08-06 17:05:02 +02006218 if (curproxy->options & PR_O_DISPATCH)
6219 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6220 else if (curproxy->options & PR_O_HTTP_PROXY)
6221 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6222 else if (curproxy->options & PR_O_TRANSP)
6223 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006224
Willy Tarreau1620ec32011-08-06 17:05:02 +02006225 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6226 if (curproxy->options & PR_O_DISABLE404) {
6227 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6228 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6229 err_code |= ERR_WARN;
6230 curproxy->options &= ~PR_O_DISABLE404;
6231 }
6232 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6233 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6234 "send-state", proxy_type_str(curproxy), curproxy->id);
6235 err_code |= ERR_WARN;
6236 curproxy->options &= ~PR_O2_CHK_SNDST;
6237 }
Willy Tarreauef781042010-01-27 11:53:01 +01006238 }
6239
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006240 /* if a default backend was specified, let's find it */
6241 if (curproxy->defbe.name) {
6242 struct proxy *target;
6243
Alex Williams96532db2009-11-01 21:27:13 -05006244 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006245 if (!target) {
6246 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6247 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006248 cfgerr++;
6249 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006250 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6251 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006252 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006253 } else {
6254 free(curproxy->defbe.name);
6255 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006256 /* we force the backend to be present on at least all of
6257 * the frontend's processes.
6258 */
6259 target->bind_proc = curproxy->bind_proc ?
6260 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006261
6262 /* Emit a warning if this proxy also has some servers */
6263 if (curproxy->srv) {
6264 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6265 curproxy->id);
6266 err_code |= ERR_WARN;
6267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 }
6269 }
6270
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006271 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006272 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6273 /* map jump target for ACT_SETBE in req_rep chain */
6274 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006275 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006276 struct proxy *target;
6277
Willy Tarreaua496b602006-12-17 23:15:24 +01006278 if (exp->action != ACT_SETBE)
6279 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006280
Alex Williams96532db2009-11-01 21:27:13 -05006281 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006282 if (!target) {
6283 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6284 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006285 cfgerr++;
6286 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006287 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6288 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006289 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006290 } else {
6291 free((void *)exp->replace);
6292 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006293 /* we force the backend to be present on at least all of
6294 * the frontend's processes.
6295 */
6296 target->bind_proc = curproxy->bind_proc ?
6297 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006298 }
6299 }
6300 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006301
6302 /* find the target proxy for 'use_backend' rules */
6303 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006304 struct proxy *target;
6305
Alex Williams96532db2009-11-01 21:27:13 -05006306 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006307
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006308 if (!target) {
6309 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6310 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006311 cfgerr++;
6312 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006313 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6314 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006315 cfgerr++;
6316 } else {
6317 free((void *)rule->be.name);
6318 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006319 /* we force the backend to be present on at least all of
6320 * the frontend's processes.
6321 */
6322 target->bind_proc = curproxy->bind_proc ?
6323 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006324 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006325 }
6326
6327 /* find the target proxy for 'use_backend' rules */
6328 list_for_each_entry(srule, &curproxy->server_rules, list) {
6329 struct server *target = findserver(curproxy, srule->srv.name);
6330
6331 if (!target) {
6332 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6333 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6334 cfgerr++;
6335 continue;
6336 }
6337 free((void *)srule->srv.name);
6338 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006339 }
6340
Emeric Brunb982a3d2010-01-04 15:45:53 +01006341 /* find the target table for 'stick' rules */
6342 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6343 struct proxy *target;
6344
Emeric Brun1d33b292010-01-04 15:47:17 +01006345 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6346 if (mrule->flags & STK_IS_STORE)
6347 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6348
Emeric Brunb982a3d2010-01-04 15:45:53 +01006349 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006350 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006351 else
6352 target = curproxy;
6353
6354 if (!target) {
6355 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6356 curproxy->id, mrule->table.name);
6357 cfgerr++;
6358 }
6359 else if (target->table.size == 0) {
6360 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6361 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6362 cfgerr++;
6363 }
Willy Tarreau12785782012-04-27 21:37:17 +02006364 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6365 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006366 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6367 cfgerr++;
6368 }
6369 else {
6370 free((void *)mrule->table.name);
6371 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006372 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006373 }
6374 }
6375
6376 /* find the target table for 'store response' rules */
6377 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6378 struct proxy *target;
6379
Emeric Brun1d33b292010-01-04 15:47:17 +01006380 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6381
Emeric Brunb982a3d2010-01-04 15:45:53 +01006382 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006383 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006384 else
6385 target = curproxy;
6386
6387 if (!target) {
6388 Alert("Proxy '%s': unable to find store table '%s'.\n",
6389 curproxy->id, mrule->table.name);
6390 cfgerr++;
6391 }
6392 else if (target->table.size == 0) {
6393 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6394 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6395 cfgerr++;
6396 }
Willy Tarreau12785782012-04-27 21:37:17 +02006397 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6398 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006399 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6400 cfgerr++;
6401 }
6402 else {
6403 free((void *)mrule->table.name);
6404 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006405 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006406 }
6407 }
6408
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006409 /* find the target table for 'tcp-request' layer 4 rules */
6410 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6411 struct proxy *target;
6412
Willy Tarreaub4c84932013-07-23 19:15:30 +02006413 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006414 continue;
6415
6416 if (trule->act_prm.trk_ctr.table.n)
6417 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6418 else
6419 target = curproxy;
6420
6421 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006422 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6423 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006424 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006425 cfgerr++;
6426 }
6427 else if (target->table.size == 0) {
6428 Alert("Proxy '%s': table '%s' used but not configured.\n",
6429 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6430 cfgerr++;
6431 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006432 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6433 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6434 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 +02006435 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006436 cfgerr++;
6437 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006438 else {
6439 free(trule->act_prm.trk_ctr.table.n);
6440 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006441 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006442 * to pass a list of counters to track and allocate them right here using
6443 * stktable_alloc_data_type().
6444 */
6445 }
6446 }
6447
Willy Tarreaud1f96522010-08-03 19:34:32 +02006448 /* find the target table for 'tcp-request' layer 6 rules */
6449 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6450 struct proxy *target;
6451
Willy Tarreaub4c84932013-07-23 19:15:30 +02006452 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006453 continue;
6454
6455 if (trule->act_prm.trk_ctr.table.n)
6456 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6457 else
6458 target = curproxy;
6459
6460 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006461 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6462 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006463 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006464 cfgerr++;
6465 }
6466 else if (target->table.size == 0) {
6467 Alert("Proxy '%s': table '%s' used but not configured.\n",
6468 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6469 cfgerr++;
6470 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006471 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6472 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6473 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 +02006474 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006475 cfgerr++;
6476 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006477 else {
6478 free(trule->act_prm.trk_ctr.table.n);
6479 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006480 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006481 * to pass a list of counters to track and allocate them right here using
6482 * stktable_alloc_data_type().
6483 */
6484 }
6485 }
6486
Emeric Brun32da3c42010-09-23 18:39:19 +02006487 if (curproxy->table.peers.name) {
6488 struct peers *curpeers = peers;
6489
6490 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6491 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6492 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006493 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006494 break;
6495 }
6496 }
6497
6498 if (!curpeers) {
6499 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6500 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006501 free((void *)curproxy->table.peers.name);
6502 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006503 cfgerr++;
6504 }
6505 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006506 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6507 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006508 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006509 cfgerr++;
6510 }
6511 }
6512
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006513 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006514 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006515 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6516 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6517 "proxy", curproxy->id);
6518 cfgerr++;
6519 goto out_uri_auth_compat;
6520 }
6521
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006522 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006523 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006524 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006525 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006526
Willy Tarreau95fa4692010-02-01 13:05:50 +01006527 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6528 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006529
6530 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006531 uri_auth_compat_req[i++] = "realm";
6532 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6533 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006534
Willy Tarreau95fa4692010-02-01 13:05:50 +01006535 uri_auth_compat_req[i++] = "unless";
6536 uri_auth_compat_req[i++] = "{";
6537 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6538 uri_auth_compat_req[i++] = "}";
6539 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006540
Willy Tarreauff011f22011-01-06 17:51:27 +01006541 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6542 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006543 cfgerr++;
6544 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006545 }
6546
Willy Tarreauff011f22011-01-06 17:51:27 +01006547 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006548
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006549 if (curproxy->uri_auth->auth_realm) {
6550 free(curproxy->uri_auth->auth_realm);
6551 curproxy->uri_auth->auth_realm = NULL;
6552 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006553
6554 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006555 }
6556out_uri_auth_compat:
6557
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006558 /* compile the log format */
6559 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006560 if (curproxy->conf.logformat_string != default_http_log_format &&
6561 curproxy->conf.logformat_string != default_tcp_log_format &&
6562 curproxy->conf.logformat_string != clf_http_log_format)
6563 free(curproxy->conf.logformat_string);
6564 curproxy->conf.logformat_string = NULL;
6565 free(curproxy->conf.lfs_file);
6566 curproxy->conf.lfs_file = NULL;
6567 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006568 }
6569
Willy Tarreau62a61232013-04-12 18:13:46 +02006570 if (curproxy->conf.logformat_string) {
6571 curproxy->conf.args.ctx = ARGC_LOG;
6572 curproxy->conf.args.file = curproxy->conf.lfs_file;
6573 curproxy->conf.args.line = curproxy->conf.lfs_line;
6574 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006575 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006576 curproxy->conf.args.file = NULL;
6577 curproxy->conf.args.line = 0;
6578 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006579
Willy Tarreau62a61232013-04-12 18:13:46 +02006580 if (curproxy->conf.uniqueid_format_string) {
6581 curproxy->conf.args.ctx = ARGC_UIF;
6582 curproxy->conf.args.file = curproxy->conf.uif_file;
6583 curproxy->conf.args.line = curproxy->conf.uif_line;
6584 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006585 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006586 curproxy->conf.args.file = NULL;
6587 curproxy->conf.args.line = 0;
6588 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006589
6590 /* only now we can check if some args remain unresolved */
6591 cfgerr += smp_resolve_args(curproxy);
6592 if (!cfgerr)
6593 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006594
Willy Tarreau2738a142006-07-08 17:28:09 +02006595 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006596 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006597 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006598 (!curproxy->timeout.connect ||
6599 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006600 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006601 " | While not properly invalid, you will certainly encounter various problems\n"
6602 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006603 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006605 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006606 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006607
Willy Tarreau1fa31262007-12-03 00:36:16 +01006608 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6609 * We must still support older configurations, so let's find out whether those
6610 * parameters have been set or must be copied from contimeouts.
6611 */
6612 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006613 if (!curproxy->timeout.tarpit ||
6614 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006615 /* tarpit timeout not set. We search in the following order:
6616 * default.tarpit, curr.connect, default.connect.
6617 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006618 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006619 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006620 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006621 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006622 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006623 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006624 }
6625 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006626 (!curproxy->timeout.queue ||
6627 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006628 /* queue timeout not set. We search in the following order:
6629 * default.queue, curr.connect, default.connect.
6630 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006631 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006632 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006633 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006634 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006635 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006636 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006637 }
6638 }
6639
Willy Tarreau1620ec32011-08-06 17:05:02 +02006640 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006641 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6642 curproxy->check_req = (char *)malloc(curproxy->check_len);
6643 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006644 }
6645
Willy Tarreau193b8c62012-11-22 00:17:38 +01006646 /* ensure that cookie capture length is not too large */
6647 if (curproxy->capture_len >= global.tune.cookie_len) {
6648 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6649 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6650 err_code |= ERR_WARN;
6651 curproxy->capture_len = global.tune.cookie_len - 1;
6652 }
6653
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006654 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006655 if (curproxy->nb_req_cap) {
6656 if (curproxy->mode == PR_MODE_HTTP) {
6657 curproxy->req_cap_pool = create_pool("ptrcap",
6658 curproxy->nb_req_cap * sizeof(char *),
6659 MEM_F_SHARED);
6660 } else {
6661 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6662 proxy_type_str(curproxy), curproxy->id);
6663 err_code |= ERR_WARN;
6664 curproxy->to_log &= ~LW_REQHDR;
6665 curproxy->nb_req_cap = 0;
6666 }
6667 }
6668
6669 if (curproxy->nb_rsp_cap) {
6670 if (curproxy->mode == PR_MODE_HTTP) {
6671 curproxy->rsp_cap_pool = create_pool("ptrcap",
6672 curproxy->nb_rsp_cap * sizeof(char *),
6673 MEM_F_SHARED);
6674 } else {
6675 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6676 proxy_type_str(curproxy), curproxy->id);
6677 err_code |= ERR_WARN;
6678 curproxy->to_log &= ~LW_REQHDR;
6679 curproxy->nb_rsp_cap = 0;
6680 }
6681 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006682
Willy Tarreaubaaee002006-06-26 02:48:02 +02006683 /* first, we will invert the servers list order */
6684 newsrv = NULL;
6685 while (curproxy->srv) {
6686 struct server *next;
6687
6688 next = curproxy->srv->next;
6689 curproxy->srv->next = newsrv;
6690 newsrv = curproxy->srv;
6691 if (!next)
6692 break;
6693 curproxy->srv = next;
6694 }
6695
Willy Tarreaudd701652010-05-25 23:03:02 +02006696 /* assign automatic UIDs to servers which don't have one yet */
6697 next_id = 1;
6698 newsrv = curproxy->srv;
6699 while (newsrv != NULL) {
6700 if (!newsrv->puid) {
6701 /* server ID not set, use automatic numbering with first
6702 * spare entry starting with next_svid.
6703 */
6704 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6705 newsrv->conf.id.key = newsrv->puid = next_id;
6706 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6707 }
6708 next_id++;
6709 newsrv = newsrv->next;
6710 }
6711
Willy Tarreau20697042007-11-15 23:26:18 +01006712 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006713 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006714
Willy Tarreau62c3be22012-01-20 13:12:32 +01006715 /*
6716 * If this server supports a maxconn parameter, it needs a dedicated
6717 * tasks to fill the emptied slots when a connection leaves.
6718 * Also, resolve deferred tracking dependency if needed.
6719 */
6720 newsrv = curproxy->srv;
6721 while (newsrv != NULL) {
6722 if (newsrv->minconn > newsrv->maxconn) {
6723 /* Only 'minconn' was specified, or it was higher than or equal
6724 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6725 * this will avoid further useless expensive computations.
6726 */
6727 newsrv->maxconn = newsrv->minconn;
6728 } else if (newsrv->maxconn && !newsrv->minconn) {
6729 /* minconn was not specified, so we set it to maxconn */
6730 newsrv->minconn = newsrv->maxconn;
6731 }
6732
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006733#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006734 if (newsrv->use_ssl || newsrv->check.use_ssl)
6735 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006736#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006737
Willy Tarreau62c3be22012-01-20 13:12:32 +01006738 if (newsrv->trackit) {
6739 struct proxy *px;
6740 struct server *srv;
6741 char *pname, *sname;
6742
6743 pname = newsrv->trackit;
6744 sname = strrchr(pname, '/');
6745
6746 if (sname)
6747 *sname++ = '\0';
6748 else {
6749 sname = pname;
6750 pname = NULL;
6751 }
6752
6753 if (pname) {
6754 px = findproxy(pname, PR_CAP_BE);
6755 if (!px) {
6756 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6757 proxy_type_str(curproxy), curproxy->id,
6758 newsrv->id, pname);
6759 cfgerr++;
6760 goto next_srv;
6761 }
6762 } else
6763 px = curproxy;
6764
6765 srv = findserver(px, sname);
6766 if (!srv) {
6767 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6768 proxy_type_str(curproxy), curproxy->id,
6769 newsrv->id, sname);
6770 cfgerr++;
6771 goto next_srv;
6772 }
6773
6774 if (!(srv->state & SRV_CHECKED)) {
6775 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6776 "tracking as it does not have checks enabled.\n",
6777 proxy_type_str(curproxy), curproxy->id,
6778 newsrv->id, px->id, srv->id);
6779 cfgerr++;
6780 goto next_srv;
6781 }
6782
6783 if (curproxy != px &&
6784 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6785 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6786 "tracking: disable-on-404 option inconsistency.\n",
6787 proxy_type_str(curproxy), curproxy->id,
6788 newsrv->id, px->id, srv->id);
6789 cfgerr++;
6790 goto next_srv;
6791 }
6792
6793 /* if the other server is forced disabled, we have to do the same here */
6794 if (srv->state & SRV_MAINTAIN) {
6795 newsrv->state |= SRV_MAINTAIN;
6796 newsrv->state &= ~SRV_RUNNING;
6797 newsrv->health = 0;
6798 }
6799
6800 newsrv->track = srv;
6801 newsrv->tracknext = srv->tracknext;
6802 srv->tracknext = newsrv;
6803
6804 free(newsrv->trackit);
6805 newsrv->trackit = NULL;
6806 }
6807 next_srv:
6808 newsrv = newsrv->next;
6809 }
6810
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006811 /* We have to initialize the server lookup mechanism depending
6812 * on what LB algorithm was choosen.
6813 */
6814
6815 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6816 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6817 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006818 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6819 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6820 init_server_map(curproxy);
6821 } else {
6822 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6823 fwrr_init_server_groups(curproxy);
6824 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006825 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006826
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006827 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006828 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6829 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6830 fwlc_init_server_tree(curproxy);
6831 } else {
6832 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6833 fas_init_server_tree(curproxy);
6834 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006835 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006836
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006837 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006838 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6839 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6840 chash_init_server_tree(curproxy);
6841 } else {
6842 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6843 init_server_map(curproxy);
6844 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006845 break;
6846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006847
6848 if (curproxy->options & PR_O_LOGASAP)
6849 curproxy->to_log &= ~LW_BYTES;
6850
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006851 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006852 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006853 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6854 proxy_type_str(curproxy), curproxy->id);
6855 err_code |= ERR_WARN;
6856 }
6857
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006858 if (curproxy->mode != PR_MODE_HTTP) {
6859 int optnum;
6860
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006861 if (curproxy->uri_auth) {
6862 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6863 proxy_type_str(curproxy), curproxy->id);
6864 err_code |= ERR_WARN;
6865 curproxy->uri_auth = NULL;
6866 }
6867
Willy Tarreau87cf5142011-08-19 22:57:24 +02006868 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006869 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6870 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6871 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006872 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006873 }
6874
6875 if (curproxy->options & PR_O_ORGTO) {
6876 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6877 "originalto", proxy_type_str(curproxy), curproxy->id);
6878 err_code |= ERR_WARN;
6879 curproxy->options &= ~PR_O_ORGTO;
6880 }
6881
6882 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6883 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6884 (curproxy->cap & cfg_opts[optnum].cap) &&
6885 (curproxy->options & cfg_opts[optnum].val)) {
6886 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6887 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6888 err_code |= ERR_WARN;
6889 curproxy->options &= ~cfg_opts[optnum].val;
6890 }
6891 }
6892
6893 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6894 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6895 (curproxy->cap & cfg_opts2[optnum].cap) &&
6896 (curproxy->options2 & cfg_opts2[optnum].val)) {
6897 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6898 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6899 err_code |= ERR_WARN;
6900 curproxy->options2 &= ~cfg_opts2[optnum].val;
6901 }
6902 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006903
Pieter Baauwd551fb52013-05-08 22:49:23 +02006904#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006905 if (curproxy->conn_src.bind_hdr_occ) {
6906 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006907 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006908 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006909 err_code |= ERR_WARN;
6910 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006911#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006912 }
6913
Willy Tarreaubaaee002006-06-26 02:48:02 +02006914 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006915 * ensure that we're not cross-dressing a TCP server into HTTP.
6916 */
6917 newsrv = curproxy->srv;
6918 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006919 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006920 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6921 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006922 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006923 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006924
Willy Tarreau0cec3312011-10-31 13:49:26 +01006925 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6926 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6927 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6928 err_code |= ERR_WARN;
6929 }
6930
Willy Tarreau82ffa392013-08-13 17:19:08 +02006931 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6932 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6933 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6934 err_code |= ERR_WARN;
6935 }
6936
Pieter Baauwd551fb52013-05-08 22:49:23 +02006937#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006938 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6939 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006940 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 +01006941 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006942 err_code |= ERR_WARN;
6943 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006944#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006945 newsrv = newsrv->next;
6946 }
6947
Willy Tarreauc1a21672009-08-16 22:37:44 +02006948 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006949 if (!curproxy->accept)
6950 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006951
Willy Tarreauc1a21672009-08-16 22:37:44 +02006952 if (curproxy->tcp_req.inspect_delay ||
6953 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006954 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006955
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006956 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006957 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006958 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006959 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006960
6961 /* both TCP and HTTP must check switching rules */
6962 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6963 }
6964
6965 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006966 if (curproxy->tcp_req.inspect_delay ||
6967 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6968 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6969
Emeric Brun97679e72010-09-23 17:56:44 +02006970 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6971 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6972
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006973 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006974 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006975 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006976 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006977
6978 /* If the backend does requires RDP cookie persistence, we have to
6979 * enable the corresponding analyser.
6980 */
6981 if (curproxy->options2 & PR_O2_RDPC_PRST)
6982 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6983 }
6984
Emeric Brunc52962f2012-11-15 18:28:02 +01006985#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006986 /* Configure SSL for each bind line.
6987 * Note: if configuration fails at some point, the ->ctx member
6988 * remains NULL so that listeners can later detach.
6989 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006990 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006991 if (!bind_conf->is_ssl) {
6992 if (bind_conf->default_ctx) {
6993 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6994 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6995 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006996 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006997 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006998 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006999 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007000 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007001 cfgerr++;
7002 continue;
7003 }
7004
Emeric Brun4b3091e2012-09-24 15:48:52 +02007005 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007006 Alert("Unable to allocate SSL session cache.\n");
7007 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007008 continue;
7009 }
7010
Emeric Brunfc0421f2012-09-07 17:30:07 +02007011 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007012 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007013 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007014#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007015
Willy Tarreaue6b98942007-10-29 01:09:36 +01007016 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007017 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007018 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007019 if (!listener->luid) {
7020 /* listener ID not set, use automatic numbering with first
7021 * spare entry starting with next_luid.
7022 */
7023 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7024 listener->conf.id.key = listener->luid = next_id;
7025 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007026 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007027 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007028
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007029 /* enable separate counters */
7030 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7031 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007032 if (!listener->name)
7033 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007034 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007035
Willy Tarreaue6b98942007-10-29 01:09:36 +01007036 if (curproxy->options & PR_O_TCP_NOLING)
7037 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007038 if (!listener->maxconn)
7039 listener->maxconn = curproxy->maxconn;
7040 if (!listener->backlog)
7041 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007042 if (!listener->maxaccept)
7043 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7044
7045 /* we want to have an optimal behaviour on single process mode to
7046 * maximize the work at once, but in multi-process we want to keep
7047 * some fairness between processes, so we target half of the max
7048 * number of events to be balanced over all the processes the proxy
7049 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7050 * used to disable the limit.
7051 */
7052 if (listener->maxaccept > 0) {
7053 if (nbproc > 1)
7054 listener->maxaccept = (listener->maxaccept + 1) / 2;
7055 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7056 }
7057
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007058 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007059 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007060 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007061 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007062
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007063 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7064 listener->options |= LI_O_TCP_RULES;
7065
Willy Tarreaude3041d2010-05-31 10:56:17 +02007066 if (curproxy->mon_mask.s_addr)
7067 listener->options |= LI_O_CHK_MONNET;
7068
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007069 /* smart accept mode is automatic in HTTP mode */
7070 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007071 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007072 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7073 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007074 }
7075
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007076 /* Release unused SSL configs */
7077 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7078 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007079 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007080#ifdef USE_OPENSSL
7081 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007082 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007083 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007084 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007085 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007086#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007087 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007088
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007089 /* Check multi-process mode compatibility for the current proxy */
7090 if (global.nbproc > 1) {
7091 int nbproc = 0;
7092 if (curproxy->bind_proc) {
7093 int proc;
7094 for (proc = 0; proc < global.nbproc; proc++) {
7095 if (curproxy->bind_proc & (1 << proc)) {
7096 nbproc++;
7097 }
7098 }
7099 } else {
7100 nbproc = global.nbproc;
7101 }
7102 if (curproxy->table.peers.name) {
7103 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7104 curproxy->id);
7105 cfgerr++;
7106 }
7107 if (nbproc > 1) {
7108 if (curproxy->uri_auth) {
7109 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7110 curproxy->id);
7111 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7112 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7113 curproxy->id);
7114 }
7115 }
7116 if (curproxy->appsession_name) {
7117 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7118 curproxy->id);
7119 }
7120 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7121 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7122 curproxy->id);
7123 }
7124 }
7125 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007126
7127 /* create the task associated with the proxy */
7128 curproxy->task = task_new();
7129 if (curproxy->task) {
7130 curproxy->task->context = curproxy;
7131 curproxy->task->process = manage_proxy;
7132 /* no need to queue, it will be done automatically if some
7133 * listener gets limited.
7134 */
7135 curproxy->task->expire = TICK_ETERNITY;
7136 } else {
7137 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7138 curproxy->id);
7139 cfgerr++;
7140 }
7141
Willy Tarreaubaaee002006-06-26 02:48:02 +02007142 curproxy = curproxy->next;
7143 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007144
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007145 /* Check multi-process mode compatibility */
7146 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007147 if (global.stats_fe && !global.stats_fe->bind_proc) {
7148 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 +01007149 }
7150 }
7151
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007152 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7153 struct auth_users *curuser;
7154 int g;
7155
7156 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7157 unsigned int group_mask = 0;
7158 char *group = NULL;
7159
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007160 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007161 continue;
7162
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007163 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007164
7165 for (g = 0; g < curuserlist->grpcnt; g++)
7166 if (!strcmp(curuserlist->groups[g], group))
7167 break;
7168
7169 if (g == curuserlist->grpcnt) {
7170 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7171 curuserlist->name, group, curuser->user);
7172 err_code |= ERR_ALERT | ERR_FATAL;
7173 goto out;
7174 }
7175
7176 group_mask |= (1 << g);
7177 }
7178
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007179 free(curuser->u.groups);
7180 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007181 }
7182
7183 for (g = 0; g < curuserlist->grpcnt; g++) {
7184 char *user = NULL;
7185
7186 if (!curuserlist->groupusers[g])
7187 continue;
7188
7189 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7190 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7191 if (!strcmp(curuser->user, user))
7192 break;
7193
7194 if (!curuser) {
7195 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7196 curuserlist->name, user, curuserlist->groups[g]);
7197 err_code |= ERR_ALERT | ERR_FATAL;
7198 goto out;
7199 }
7200
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007201 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007202 }
7203
7204 free(curuserlist->groupusers[g]);
7205 }
7206
7207 free(curuserlist->groupusers);
7208
7209#ifdef DEBUG_AUTH
7210 for (g = 0; g < curuserlist->grpcnt; g++) {
7211 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7212
7213 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007214 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007215 fprintf(stderr, " %s", curuser->user);
7216 }
7217
7218 fprintf(stderr, "\n");
7219 }
7220#endif
7221
Willy Tarreaufbb78422011-06-05 15:38:35 +02007222 }
7223
7224 /* automatically compute fullconn if not set. We must not do it in the
7225 * loop above because cross-references are not yet fully resolved.
7226 */
7227 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7228 /* If <fullconn> is not set, let's set it to 10% of the sum of
7229 * the possible incoming frontend's maxconns.
7230 */
7231 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7232 struct proxy *fe;
7233 int total = 0;
7234
7235 /* sum up the number of maxconns of frontends which
7236 * reference this backend at least once or which are
7237 * the same one ('listen').
7238 */
7239 for (fe = proxy; fe; fe = fe->next) {
7240 struct switching_rule *rule;
7241 struct hdr_exp *exp;
7242 int found = 0;
7243
7244 if (!(fe->cap & PR_CAP_FE))
7245 continue;
7246
7247 if (fe == curproxy) /* we're on a "listen" instance */
7248 found = 1;
7249
7250 if (fe->defbe.be == curproxy) /* "default_backend" */
7251 found = 1;
7252
7253 /* check if a "use_backend" rule matches */
7254 if (!found) {
7255 list_for_each_entry(rule, &fe->switching_rules, list) {
7256 if (rule->be.backend == curproxy) {
7257 found = 1;
7258 break;
7259 }
7260 }
7261 }
7262
7263 /* check if a "reqsetbe" rule matches */
7264 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7265 if (exp->action == ACT_SETBE &&
7266 (struct proxy *)exp->replace == curproxy) {
7267 found = 1;
7268 break;
7269 }
7270 }
7271
7272 /* now we've checked all possible ways to reference a backend
7273 * from a frontend.
7274 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007275 if (!found)
7276 continue;
7277 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007278 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007279 /* we have the sum of the maxconns in <total>. We only
7280 * keep 10% of that sum to set the default fullconn, with
7281 * a hard minimum of 1 (to avoid a divide by zero).
7282 */
7283 curproxy->fullconn = (total + 9) / 10;
7284 if (!curproxy->fullconn)
7285 curproxy->fullconn = 1;
7286 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007287 }
7288
Willy Tarreau056f5682010-06-06 15:51:11 +02007289 /* initialize stick-tables on backend capable proxies. This must not
7290 * be done earlier because the data size may be discovered while parsing
7291 * other proxies.
7292 */
7293 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007294 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007295
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007296 /*
7297 * Recount currently required checks.
7298 */
7299
7300 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7301 int optnum;
7302
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007303 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7304 if (curproxy->options & cfg_opts[optnum].val)
7305 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007306
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007307 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7308 if (curproxy->options2 & cfg_opts2[optnum].val)
7309 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007310 }
7311
Willy Tarreau122541c2011-09-07 21:24:49 +02007312 if (peers) {
7313 struct peers *curpeers = peers, **last;
7314 struct peer *p, *pb;
7315
7316 /* Remove all peers sections which don't have a valid listener.
7317 * This can happen when a peers section is never referenced and
7318 * does not contain a local peer.
7319 */
7320 last = &peers;
7321 while (*last) {
7322 curpeers = *last;
7323 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007324 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007325 last = &curpeers->next;
7326 continue;
7327 }
7328
7329 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7330 curpeers->id, localpeer);
7331
7332 p = curpeers->remote;
7333 while (p) {
7334 pb = p->next;
7335 free(p->id);
7336 free(p);
7337 p = pb;
7338 }
7339
7340 /* Destroy and unlink this curpeers section.
7341 * Note: curpeers is backed up into *last.
7342 */
7343 free(curpeers->id);
7344 curpeers = curpeers->next;
7345 free(*last);
7346 *last = curpeers;
7347 }
7348 }
7349
Willy Tarreau34eb6712011-10-24 18:15:04 +02007350 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007351 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007352 MEM_F_SHARED);
7353
Willy Tarreaubb925012009-07-23 13:36:36 +02007354 if (cfgerr > 0)
7355 err_code |= ERR_ALERT | ERR_FATAL;
7356 out:
7357 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007358}
7359
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007360/*
7361 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7362 * parsing sessions.
7363 */
7364void cfg_register_keywords(struct cfg_kw_list *kwl)
7365{
7366 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7367}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007368
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007369/*
7370 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7371 */
7372void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7373{
7374 LIST_DEL(&kwl->list);
7375 LIST_INIT(&kwl->list);
7376}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007377
7378/*
7379 * Local variables:
7380 * c-indent-level: 8
7381 * c-basic-offset: 8
7382 * End:
7383 */