blob: 28507dd0649063f65fc30265649bc77cab208a7c [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
1325 defproxy.defsrv.inter = DEF_CHKINTR;
1326 defproxy.defsrv.fastinter = 0;
1327 defproxy.defsrv.downinter = 0;
1328 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;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004244 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4245 newsrv->xprt = newsrv->check.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
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004254 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004255 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004256 newsrv->inter = curproxy->defsrv.inter;
4257 newsrv->fastinter = curproxy->defsrv.fastinter;
4258 newsrv->downinter = curproxy->defsrv.downinter;
4259 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 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004346 newsrv->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 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004363 newsrv->fastinter = val;
4364 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 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004380 newsrv->downinter = val;
4381 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
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004411 newsrv->check.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 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004847 if (!newsrv->check.port && !is_addr(&newsrv->check.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 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004853 /* try to get the port from check.addr if check.port not set */
4854 if (!newsrv->check.port)
4855 newsrv->check.port = get_host_port(&newsrv->check.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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 newsrv->state |= SRV_CHECKED;
4906 }
4907
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004908 if (!defsrv) {
4909 if (newsrv->state & SRV_BACKUP)
4910 curproxy->srv_bck++;
4911 else
4912 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004913
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004914 newsrv->prev_state = newsrv->state;
4915 }
William Lallemanda73203e2012-03-12 12:48:57 +01004916 }
4917
4918 else if (strcmp(args[0], "unique-id-format") == 0) {
4919 if (!*(args[1])) {
4920 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
William Lallemand3203ff42012-11-11 17:30:56 +01004924 if (*(args[2])) {
4925 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
4928 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004929 free(curproxy->conf.uniqueid_format_string);
4930 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004931
Willy Tarreau62a61232013-04-12 18:13:46 +02004932 free(curproxy->conf.uif_file);
4933 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4934 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004935 }
William Lallemanda73203e2012-03-12 12:48:57 +01004936
4937 else if (strcmp(args[0], "unique-id-header") == 0) {
4938 if (!*(args[1])) {
4939 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943 free(curproxy->header_unique_id);
4944 curproxy->header_unique_id = strdup(args[1]);
4945 }
4946
William Lallemand723b73a2012-02-08 16:37:49 +01004947 else if (strcmp(args[0], "log-format") == 0) {
4948 if (!*(args[1])) {
4949 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
William Lallemand3203ff42012-11-11 17:30:56 +01004953 if (*(args[2])) {
4954 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004958
Willy Tarreau62a61232013-04-12 18:13:46 +02004959 if (curproxy->conf.logformat_string != default_http_log_format &&
4960 curproxy->conf.logformat_string != default_tcp_log_format &&
4961 curproxy->conf.logformat_string != clf_http_log_format)
4962 free(curproxy->conf.logformat_string);
4963 curproxy->conf.logformat_string = strdup(args[1]);
4964
4965 free(curproxy->conf.lfs_file);
4966 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4967 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004968
4969 /* get a chance to improve log-format error reporting by
4970 * reporting the correct line-number when possible.
4971 */
4972 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4973 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4974 file, linenum, curproxy->id);
4975 err_code |= ERR_WARN;
4976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 }
William Lallemand723b73a2012-02-08 16:37:49 +01004978
William Lallemand0f99e342011-10-12 17:50:54 +02004979 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4980 /* delete previous herited or defined syslog servers */
4981 struct logsrv *back;
4982
4983 if (*(args[1]) != 0) {
4984 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
4987 }
4988
William Lallemand723b73a2012-02-08 16:37:49 +01004989 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4990 LIST_DEL(&tmplogsrv->list);
4991 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004992 }
4993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004995 struct logsrv *logsrv;
4996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004998 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004999 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005000 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005001 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005002 LIST_INIT(&node->list);
5003 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
5006 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005007 struct sockaddr_storage *sk;
5008 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005009
5010 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011
William Lallemand0f99e342011-10-12 17:50:54 +02005012 logsrv->facility = get_log_facility(args[2]);
5013 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
5019
William Lallemand0f99e342011-10-12 17:50:54 +02005020 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005022 logsrv->level = get_log_level(args[3]);
5023 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029 }
5030
William Lallemand0f99e342011-10-12 17:50:54 +02005031 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005032 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005033 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005034 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005035 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005039 }
5040 }
5041
Willy Tarreau902636f2013-03-10 19:44:48 +01005042 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005043 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005044 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005045 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005046 goto out;
5047 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005048
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005049 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005050
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005051 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005052 if (port1 != port2) {
5053 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5054 file, linenum, args[0], args[1]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005059 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005060 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
William Lallemand0f99e342011-10-12 17:50:54 +02005062
5063 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else {
5066 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5067 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 }
5071 }
5072 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005073 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005074 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005075 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005076 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005077
Willy Tarreau977b8e42006-12-29 14:19:17 +01005078 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005080
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005082 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5083 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005087
5088 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005089 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5090 free(curproxy->conn_src.iface_name);
5091 curproxy->conn_src.iface_name = NULL;
5092 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005093
Willy Tarreau902636f2013-03-10 19:44:48 +01005094 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005095 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005096 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005097 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005099 goto out;
5100 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005101
5102 proto = protocol_by_family(sk->ss_family);
5103 if (!proto || !proto->connect) {
5104 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005105 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
5108 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005109
5110 if (port1 != port2) {
5111 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5112 file, linenum, args[0], args[1]);
5113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115 }
5116
Willy Tarreauef9a3602012-12-08 22:29:20 +01005117 curproxy->conn_src.source_addr = *sk;
5118 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005119
5120 cur_arg = 2;
5121 while (*(args[cur_arg])) {
5122 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005123#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5124#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005125 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005126 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5127 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005130 }
5131#endif
5132 if (!*args[cur_arg + 1]) {
5133 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5134 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 }
5138
5139 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005140 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5141 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005142 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005143 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5144 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005145 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5146 char *name, *end;
5147
5148 name = args[cur_arg+1] + 7;
5149 while (isspace(*name))
5150 name++;
5151
5152 end = name;
5153 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5154 end++;
5155
Willy Tarreauef9a3602012-12-08 22:29:20 +01005156 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5157 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5158 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5159 curproxy->conn_src.bind_hdr_len = end - name;
5160 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5161 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5162 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005163
5164 /* now look for an occurrence number */
5165 while (isspace(*end))
5166 end++;
5167 if (*end == ',') {
5168 end++;
5169 name = end;
5170 if (*end == '-')
5171 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005172 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005173 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005174 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005175 }
5176
Willy Tarreauef9a3602012-12-08 22:29:20 +01005177 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005178 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5179 " occurrences values smaller than %d.\n",
5180 file, linenum, MAX_HDR_HISTORY);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005184 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005185 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005186
Willy Tarreau902636f2013-03-10 19:44:48 +01005187 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005188 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005189 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005190 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005191 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005192 goto out;
5193 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005194
5195 proto = protocol_by_family(sk->ss_family);
5196 if (!proto || !proto->connect) {
5197 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5198 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005202
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005203 if (port1 != port2) {
5204 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5205 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005209 curproxy->conn_src.tproxy_addr = *sk;
5210 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005211 }
5212 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005213#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005214 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005215#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005216#else /* no TPROXY support */
5217 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005218 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005221#endif
5222 cur_arg += 2;
5223 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005224 }
5225
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005226 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5227#ifdef SO_BINDTODEVICE
5228 if (!*args[cur_arg + 1]) {
5229 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005233 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005234 free(curproxy->conn_src.iface_name);
5235 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5236 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005237 global.last_checks |= LSTCHK_NETADM;
5238#else
5239 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5240 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005243#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005244 cur_arg += 2;
5245 continue;
5246 }
5247 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005248 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005253 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5254 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5255 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266
5267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
5280 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005297 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005301 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005303 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005306 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005307 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005308 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005310 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005311 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005313 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005314 }
5315 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005316 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005317 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005318 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005319 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005320 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005323 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329
5330 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005331 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005332 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005333 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
5336 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005338 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005339 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 }
5343 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005345 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
5350 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005352 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005353 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005354 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
5357 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005359 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005360 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005364 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005366 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005369 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005372 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005373
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 if (curproxy == &defproxy) {
5375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005379 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 if (*(args[1]) == 0) {
5383 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005387
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005388 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005389 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5390 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5391 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005395 err_code |= warnif_cond_conflicts(cond,
5396 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5397 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005398 }
5399 else if (*args[2]) {
5400 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5401 file, linenum, args[0], args[2]);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
5405
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005406 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005407 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005408 wl->s = strdup(args[1]);
5409 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005410 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 }
5412 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005413 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5415 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005419
Willy Tarreauade5ec42010-01-28 19:33:49 +01005420 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005421 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005422 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005423 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 }
5426 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005427 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005428 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005429 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005430 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 }
5433 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005434 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005435 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005436 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005437 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 }
5440 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005441 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5443 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
5447
Willy Tarreauade5ec42010-01-28 19:33:49 +01005448 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005449 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005450 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005451 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
5454 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005455 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005456 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005457 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005458 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 }
5461 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005462 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005463 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005464 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005465 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 }
5468 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005469 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005470
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 if (curproxy == &defproxy) {
5472 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005476 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 if (*(args[1]) == 0) {
5480 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
5484
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005485 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005486 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5487 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5488 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
5491 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005492 err_code |= warnif_cond_conflicts(cond,
5493 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5494 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005495 }
5496 else if (*args[2]) {
5497 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5498 file, linenum, args[0], args[2]);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005503 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005504 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005505 wl->s = strdup(args[1]);
5506 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 }
5508 else if (!strcmp(args[0], "errorloc") ||
5509 !strcmp(args[0], "errorloc302") ||
5510 !strcmp(args[0], "errorloc303")) { /* error location */
5511 int errnum, errlen;
5512 char *err;
5513
Willy Tarreau977b8e42006-12-29 14:19:17 +01005514 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005515 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005516
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005518 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 }
5522
5523 errnum = atol(args[1]);
5524 if (!strcmp(args[0], "errorloc303")) {
5525 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5526 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5527 } else {
5528 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5529 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5530 }
5531
Willy Tarreau0f772532006-12-23 20:51:41 +01005532 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5533 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005534 chunk_destroy(&curproxy->errmsg[rc]);
5535 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005536 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005539
5540 if (rc >= HTTP_ERR_SIZE) {
5541 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5542 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 free(err);
5544 }
5545 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005546 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5547 int errnum, errlen, fd;
5548 char *err;
5549 struct stat stat;
5550
5551 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005552 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005553
5554 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005555 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005558 }
5559
5560 fd = open(args[2], O_RDONLY);
5561 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5562 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5563 file, linenum, args[2], args[1]);
5564 if (fd >= 0)
5565 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005568 }
5569
Willy Tarreau27a674e2009-08-17 07:23:33 +02005570 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005571 errlen = stat.st_size;
5572 } else {
5573 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005574 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005575 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005576 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005577 }
5578
5579 err = malloc(errlen); /* malloc() must succeed during parsing */
5580 errnum = read(fd, err, errlen);
5581 if (errnum != errlen) {
5582 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5583 file, linenum, args[2], args[1]);
5584 close(fd);
5585 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005586 err_code |= ERR_ALERT | ERR_FATAL;
5587 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005588 }
5589 close(fd);
5590
5591 errnum = atol(args[1]);
5592 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5593 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005594 chunk_destroy(&curproxy->errmsg[rc]);
5595 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005596 break;
5597 }
5598 }
5599
5600 if (rc >= HTTP_ERR_SIZE) {
5601 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5602 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005603 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005604 free(err);
5605 }
5606 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005607 else if (!strcmp(args[0], "compression")) {
5608 struct comp *comp;
5609 if (curproxy->comp == NULL) {
5610 comp = calloc(1, sizeof(struct comp));
5611 curproxy->comp = comp;
5612 } else {
5613 comp = curproxy->comp;
5614 }
5615
5616 if (!strcmp(args[1], "algo")) {
5617 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005618 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005619
William Lallemand82fe75c2012-10-23 10:25:10 +02005620 cur_arg = 2;
5621 if (!*args[cur_arg]) {
5622 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5623 file, linenum, args[0]);
5624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
5626 }
5627 while (*(args[cur_arg])) {
5628 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5629 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5630 file, linenum, args[0], args[cur_arg]);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
William Lallemand552df672012-11-07 13:21:47 +01005634 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5635 curproxy->comp->algos->end(&ctx);
5636 } else {
5637 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5638 file, linenum, args[0], args[cur_arg]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005642 cur_arg ++;
5643 continue;
5644 }
5645 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005646 else if (!strcmp(args[1], "offload")) {
5647 comp->offload = 1;
5648 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005649 else if (!strcmp(args[1], "type")) {
5650 int cur_arg;
5651 cur_arg = 2;
5652 if (!*args[cur_arg]) {
5653 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5654 file, linenum, args[0]);
5655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
5657 }
5658 while (*(args[cur_arg])) {
5659 comp_append_type(comp, args[cur_arg]);
5660 cur_arg ++;
5661 continue;
5662 }
5663 }
5664 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005665 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005666 file, linenum, args[0]);
5667 err_code |= ERR_ALERT | ERR_FATAL;
5668 goto out;
5669 }
5670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005672 struct cfg_kw_list *kwl;
5673 int index;
5674
5675 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5676 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5677 if (kwl->kw[index].section != CFG_LISTEN)
5678 continue;
5679 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5680 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005681 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005682 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005683 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005686 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005687 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005688 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_WARN;
5690 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005691 }
Willy Tarreau93893792009-07-23 13:19:11 +02005692 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005693 }
5694 }
5695 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005696
Willy Tarreau6daf3432008-01-22 16:44:08 +01005697 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 }
Willy Tarreau93893792009-07-23 13:19:11 +02005701 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005702 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704}
5705
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005706int
5707cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5708{
5709
5710 int err_code = 0;
5711 const char *err;
5712
5713 if (!strcmp(args[0], "userlist")) { /* new userlist */
5714 struct userlist *newul;
5715
5716 if (!*args[1]) {
5717 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5718 file, linenum, args[0]);
5719 err_code |= ERR_ALERT | ERR_FATAL;
5720 goto out;
5721 }
5722
5723 err = invalid_char(args[1]);
5724 if (err) {
5725 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5726 file, linenum, *err, args[0], args[1]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
5730
5731 for (newul = userlist; newul; newul = newul->next)
5732 if (!strcmp(newul->name, args[1])) {
5733 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5734 file, linenum, args[1]);
5735 err_code |= ERR_WARN;
5736 goto out;
5737 }
5738
5739 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5740 if (!newul) {
5741 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5742 err_code |= ERR_ALERT | ERR_ABORT;
5743 goto out;
5744 }
5745
5746 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5747 newul->name = strdup(args[1]);
5748
5749 if (!newul->groupusers | !newul->name) {
5750 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5751 err_code |= ERR_ALERT | ERR_ABORT;
5752 goto out;
5753 }
5754
5755 newul->next = userlist;
5756 userlist = newul;
5757
5758 } else if (!strcmp(args[0], "group")) { /* new group */
5759 int cur_arg, i;
5760 const char *err;
5761
5762 if (!*args[1]) {
5763 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5764 file, linenum, args[0]);
5765 err_code |= ERR_ALERT | ERR_FATAL;
5766 goto out;
5767 }
5768
5769 err = invalid_char(args[1]);
5770 if (err) {
5771 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5772 file, linenum, *err, args[0], args[1]);
5773 err_code |= ERR_ALERT | ERR_FATAL;
5774 goto out;
5775 }
5776
5777 for(i = 0; i < userlist->grpcnt; i++)
5778 if (!strcmp(userlist->groups[i], args[1])) {
5779 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5780 file, linenum, args[1], userlist->name);
5781 err_code |= ERR_ALERT;
5782 goto out;
5783 }
5784
5785 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5786 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5787 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5788 err_code |= ERR_ALERT | ERR_FATAL;
5789 goto out;
5790 }
5791
5792 cur_arg = 2;
5793
5794 while (*args[cur_arg]) {
5795 if (!strcmp(args[cur_arg], "users")) {
5796 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5797 cur_arg += 2;
5798 continue;
5799 } else {
5800 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5801 file, linenum, args[0]);
5802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
5805 }
5806
5807 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5808 } else if (!strcmp(args[0], "user")) { /* new user */
5809 struct auth_users *newuser;
5810 int cur_arg;
5811
5812 if (!*args[1]) {
5813 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5814 file, linenum, args[0]);
5815 err_code |= ERR_ALERT | ERR_FATAL;
5816 goto out;
5817 }
5818
5819 for (newuser = userlist->users; newuser; newuser = newuser->next)
5820 if (!strcmp(newuser->user, args[1])) {
5821 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5822 file, linenum, args[1], userlist->name);
5823 err_code |= ERR_ALERT;
5824 goto out;
5825 }
5826
5827 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5828 if (!newuser) {
5829 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5830 err_code |= ERR_ALERT | ERR_ABORT;
5831 goto out;
5832 }
5833
5834 newuser->user = strdup(args[1]);
5835
5836 newuser->next = userlist->users;
5837 userlist->users = newuser;
5838
5839 cur_arg = 2;
5840
5841 while (*args[cur_arg]) {
5842 if (!strcmp(args[cur_arg], "password")) {
5843#ifndef CONFIG_HAP_CRYPT
5844 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5845 file, linenum);
5846 err_code |= ERR_ALERT;
5847#endif
5848 newuser->pass = strdup(args[cur_arg + 1]);
5849 cur_arg += 2;
5850 continue;
5851 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5852 newuser->pass = strdup(args[cur_arg + 1]);
5853 newuser->flags |= AU_O_INSECURE;
5854 cur_arg += 2;
5855 continue;
5856 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005857 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005858 cur_arg += 2;
5859 continue;
5860 } else {
5861 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5862 file, linenum, args[0]);
5863 err_code |= ERR_ALERT | ERR_FATAL;
5864 goto out;
5865 }
5866 }
5867 } else {
5868 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5869 err_code |= ERR_ALERT | ERR_FATAL;
5870 }
5871
5872out:
5873 return err_code;
5874}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875
5876/*
5877 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005878 * Returns the error code, 0 if OK, or any combination of :
5879 * - ERR_ABORT: must abort ASAP
5880 * - ERR_FATAL: we can continue parsing but not start the service
5881 * - ERR_WARN: a warning has been emitted
5882 * - ERR_ALERT: an alert has been emitted
5883 * Only the two first ones can stop processing, the two others are just
5884 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005886int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005888 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 FILE *f;
5890 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005892 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005893
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 if ((f=fopen(file,"r")) == NULL)
5895 return -1;
5896
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005897 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005898 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005899 char *end;
5900 char *args[MAX_LINE_ARGS + 1];
5901 char *line = thisline;
5902
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 linenum++;
5904
5905 end = line + strlen(line);
5906
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005907 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5908 /* Check if we reached the limit and the last char is not \n.
5909 * Watch out for the last line without the terminating '\n'!
5910 */
5911 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005912 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005914 }
5915
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005917 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 line++;
5919
5920 arg = 0;
5921 args[arg] = line;
5922
5923 while (*line && arg < MAX_LINE_ARGS) {
5924 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5925 * C equivalent value. Other combinations left unchanged (eg: \1).
5926 */
5927 if (*line == '\\') {
5928 int skip = 0;
5929 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5930 *line = line[1];
5931 skip = 1;
5932 }
5933 else if (line[1] == 'r') {
5934 *line = '\r';
5935 skip = 1;
5936 }
5937 else if (line[1] == 'n') {
5938 *line = '\n';
5939 skip = 1;
5940 }
5941 else if (line[1] == 't') {
5942 *line = '\t';
5943 skip = 1;
5944 }
5945 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005946 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 unsigned char hex1, hex2;
5948 hex1 = toupper(line[2]) - '0';
5949 hex2 = toupper(line[3]) - '0';
5950 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5951 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5952 *line = (hex1<<4) + hex2;
5953 skip = 3;
5954 }
5955 else {
5956 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005957 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 }
5959 }
5960 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005961 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 end -= skip;
5963 }
5964 line++;
5965 }
5966 else if (*line == '#' || *line == '\n' || *line == '\r') {
5967 /* end of string, end of loop */
5968 *line = 0;
5969 break;
5970 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005971 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005973 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005974 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 line++;
5976 args[++arg] = line;
5977 }
5978 else {
5979 line++;
5980 }
5981 }
5982
5983 /* empty line */
5984 if (!**args)
5985 continue;
5986
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005987 if (*line) {
5988 /* we had to stop due to too many args.
5989 * Let's terminate the string, print the offending part then cut the
5990 * last arg.
5991 */
5992 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5993 line++;
5994 *line = '\0';
5995
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005996 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005997 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005998 err_code |= ERR_ALERT | ERR_FATAL;
5999 args[arg] = line;
6000 }
6001
Willy Tarreau540abe42007-05-02 20:50:16 +02006002 /* zero out remaining args and ensure that at least one entry
6003 * is zeroed out.
6004 */
6005 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006006 args[arg] = line;
6007 }
6008
Willy Tarreau3842f002009-06-14 11:39:52 +02006009 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006010 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006011 char *tmp;
6012
Willy Tarreau3842f002009-06-14 11:39:52 +02006013 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006014 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006015 for (arg=0; *args[arg+1]; arg++)
6016 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006017 *tmp = '\0'; // fix the next arg to \0
6018 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006019 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006020 else if (!strcmp(args[0], "default")) {
6021 kwm = KWM_DEF;
6022 for (arg=0; *args[arg+1]; arg++)
6023 args[arg] = args[arg+1]; // shift args after inversion
6024 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006025
William Lallemand0f99e342011-10-12 17:50:54 +02006026 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6027 strcmp(args[0], "log") != 0) {
6028 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006029 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006030 }
6031
Willy Tarreau977b8e42006-12-29 14:19:17 +01006032 if (!strcmp(args[0], "listen") ||
6033 !strcmp(args[0], "frontend") ||
6034 !strcmp(args[0], "backend") ||
6035 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006036 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006038 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006039 cursection = strdup(args[0]);
6040 }
6041 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006043 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006044 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006045 }
6046 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006047 confsect = CFG_USERLIST;
6048 free(cursection);
6049 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006050 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006051 else if (!strcmp(args[0], "peers")) {
6052 confsect = CFG_PEERS;
6053 free(cursection);
6054 cursection = strdup(args[0]);
6055 }
6056
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 /* else it's a section keyword */
6058
6059 switch (confsect) {
6060 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006061 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062 break;
6063 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006064 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006066 case CFG_USERLIST:
6067 err_code |= cfg_parse_users(file, linenum, args, kwm);
6068 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006069 case CFG_PEERS:
6070 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6071 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006072 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006073 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006076
6077 if (err_code & ERR_ABORT)
6078 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006079 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006080 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006081 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006082 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006083 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006084}
6085
Willy Tarreaubb925012009-07-23 13:36:36 +02006086/*
6087 * Returns the error code, 0 if OK, or any combination of :
6088 * - ERR_ABORT: must abort ASAP
6089 * - ERR_FATAL: we can continue parsing but not start the service
6090 * - ERR_WARN: a warning has been emitted
6091 * - ERR_ALERT: an alert has been emitted
6092 * Only the two first ones can stop processing, the two others are just
6093 * indicators.
6094 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006095int check_config_validity()
6096{
6097 int cfgerr = 0;
6098 struct proxy *curproxy = NULL;
6099 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006100 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006101 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006102 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006103 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006104
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006105 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006106 /*
6107 * Now, check for the integrity of all that we have collected.
6108 */
6109
6110 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006111 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112
Willy Tarreau193b8c62012-11-22 00:17:38 +01006113 if (!global.tune.max_http_hdr)
6114 global.tune.max_http_hdr = MAX_HTTP_HDR;
6115
6116 if (!global.tune.cookie_len)
6117 global.tune.cookie_len = CAPTURE_LEN;
6118
6119 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6120
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006121 /* first, we will invert the proxy list order */
6122 curproxy = NULL;
6123 while (proxy) {
6124 struct proxy *next;
6125
6126 next = proxy->next;
6127 proxy->next = curproxy;
6128 curproxy = proxy;
6129 if (!next)
6130 break;
6131 proxy = next;
6132 }
6133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006135 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006136 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006137 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006138 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006139 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006140 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006141 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006142
Willy Tarreau050536d2012-10-04 08:47:34 +02006143 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006144 /* proxy ID not set, use automatic numbering with first
6145 * spare entry starting with next_pxid.
6146 */
6147 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6148 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6149 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006150 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006151 next_pxid++;
6152
Willy Tarreau55ea7572007-06-17 19:56:27 +02006153
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006155 /* ensure we don't keep listeners uselessly bound */
6156 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 curproxy = curproxy->next;
6158 continue;
6159 }
6160
Willy Tarreau16a21472012-11-19 12:39:59 +01006161 /* number of processes this proxy is bound to */
6162 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6163
Willy Tarreauff01a212009-03-15 13:46:16 +01006164 switch (curproxy->mode) {
6165 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006166 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006167 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6169 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006170 cfgerr++;
6171 }
6172
6173 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006174 Warning("config : servers will be ignored for %s '%s'.\n",
6175 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006176 break;
6177
6178 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006179 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006180 break;
6181
6182 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006183 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006184 break;
6185 }
6186
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006187 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006188 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006189 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006190 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6191 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006192 cfgerr++;
6193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006195 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006196 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6197 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006198 cfgerr++;
6199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006201 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006202 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6203 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006204 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006205 }
6206 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006207 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006208 /* If no LB algo is set in a backend, and we're not in
6209 * transparent mode, dispatch mode nor proxy mode, we
6210 * want to use balance roundrobin by default.
6211 */
6212 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6213 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 }
6215 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006216
Willy Tarreau1620ec32011-08-06 17:05:02 +02006217 if (curproxy->options & PR_O_DISPATCH)
6218 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6219 else if (curproxy->options & PR_O_HTTP_PROXY)
6220 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6221 else if (curproxy->options & PR_O_TRANSP)
6222 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006223
Willy Tarreau1620ec32011-08-06 17:05:02 +02006224 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6225 if (curproxy->options & PR_O_DISABLE404) {
6226 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6227 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6228 err_code |= ERR_WARN;
6229 curproxy->options &= ~PR_O_DISABLE404;
6230 }
6231 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6232 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6233 "send-state", proxy_type_str(curproxy), curproxy->id);
6234 err_code |= ERR_WARN;
6235 curproxy->options &= ~PR_O2_CHK_SNDST;
6236 }
Willy Tarreauef781042010-01-27 11:53:01 +01006237 }
6238
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006239 /* if a default backend was specified, let's find it */
6240 if (curproxy->defbe.name) {
6241 struct proxy *target;
6242
Alex Williams96532db2009-11-01 21:27:13 -05006243 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006244 if (!target) {
6245 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6246 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006247 cfgerr++;
6248 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006249 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6250 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006251 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006252 } else {
6253 free(curproxy->defbe.name);
6254 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006255 /* we force the backend to be present on at least all of
6256 * the frontend's processes.
6257 */
6258 target->bind_proc = curproxy->bind_proc ?
6259 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006260
6261 /* Emit a warning if this proxy also has some servers */
6262 if (curproxy->srv) {
6263 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6264 curproxy->id);
6265 err_code |= ERR_WARN;
6266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
6268 }
6269
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006270 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006271 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6272 /* map jump target for ACT_SETBE in req_rep chain */
6273 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006274 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006275 struct proxy *target;
6276
Willy Tarreaua496b602006-12-17 23:15:24 +01006277 if (exp->action != ACT_SETBE)
6278 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006279
Alex Williams96532db2009-11-01 21:27:13 -05006280 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006281 if (!target) {
6282 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6283 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006284 cfgerr++;
6285 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006286 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6287 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006288 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006289 } else {
6290 free((void *)exp->replace);
6291 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006292 /* we force the backend to be present on at least all of
6293 * the frontend's processes.
6294 */
6295 target->bind_proc = curproxy->bind_proc ?
6296 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006297 }
6298 }
6299 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006300
6301 /* find the target proxy for 'use_backend' rules */
6302 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006303 struct proxy *target;
6304
Alex Williams96532db2009-11-01 21:27:13 -05006305 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006306
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006307 if (!target) {
6308 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6309 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006310 cfgerr++;
6311 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006312 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6313 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006314 cfgerr++;
6315 } else {
6316 free((void *)rule->be.name);
6317 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006318 /* we force the backend to be present on at least all of
6319 * the frontend's processes.
6320 */
6321 target->bind_proc = curproxy->bind_proc ?
6322 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006323 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006324 }
6325
6326 /* find the target proxy for 'use_backend' rules */
6327 list_for_each_entry(srule, &curproxy->server_rules, list) {
6328 struct server *target = findserver(curproxy, srule->srv.name);
6329
6330 if (!target) {
6331 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6332 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6333 cfgerr++;
6334 continue;
6335 }
6336 free((void *)srule->srv.name);
6337 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006338 }
6339
Emeric Brunb982a3d2010-01-04 15:45:53 +01006340 /* find the target table for 'stick' rules */
6341 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6342 struct proxy *target;
6343
Emeric Brun1d33b292010-01-04 15:47:17 +01006344 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6345 if (mrule->flags & STK_IS_STORE)
6346 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6347
Emeric Brunb982a3d2010-01-04 15:45:53 +01006348 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006349 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006350 else
6351 target = curproxy;
6352
6353 if (!target) {
6354 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6355 curproxy->id, mrule->table.name);
6356 cfgerr++;
6357 }
6358 else if (target->table.size == 0) {
6359 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6360 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6361 cfgerr++;
6362 }
Willy Tarreau12785782012-04-27 21:37:17 +02006363 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6364 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006365 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6366 cfgerr++;
6367 }
6368 else {
6369 free((void *)mrule->table.name);
6370 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006371 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006372 }
6373 }
6374
6375 /* find the target table for 'store response' rules */
6376 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6377 struct proxy *target;
6378
Emeric Brun1d33b292010-01-04 15:47:17 +01006379 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6380
Emeric Brunb982a3d2010-01-04 15:45:53 +01006381 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006382 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006383 else
6384 target = curproxy;
6385
6386 if (!target) {
6387 Alert("Proxy '%s': unable to find store table '%s'.\n",
6388 curproxy->id, mrule->table.name);
6389 cfgerr++;
6390 }
6391 else if (target->table.size == 0) {
6392 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6393 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6394 cfgerr++;
6395 }
Willy Tarreau12785782012-04-27 21:37:17 +02006396 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6397 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006398 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6399 cfgerr++;
6400 }
6401 else {
6402 free((void *)mrule->table.name);
6403 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006404 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006405 }
6406 }
6407
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006408 /* find the target table for 'tcp-request' layer 4 rules */
6409 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6410 struct proxy *target;
6411
Willy Tarreaub4c84932013-07-23 19:15:30 +02006412 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006413 continue;
6414
6415 if (trule->act_prm.trk_ctr.table.n)
6416 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6417 else
6418 target = curproxy;
6419
6420 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006421 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6422 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006423 1 + tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006424 cfgerr++;
6425 }
6426 else if (target->table.size == 0) {
6427 Alert("Proxy '%s': table '%s' used but not configured.\n",
6428 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6429 cfgerr++;
6430 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006431 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6432 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6433 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 +02006434 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006435 cfgerr++;
6436 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006437 else {
6438 free(trule->act_prm.trk_ctr.table.n);
6439 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006440 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006441 * to pass a list of counters to track and allocate them right here using
6442 * stktable_alloc_data_type().
6443 */
6444 }
6445 }
6446
Willy Tarreaud1f96522010-08-03 19:34:32 +02006447 /* find the target table for 'tcp-request' layer 6 rules */
6448 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6449 struct proxy *target;
6450
Willy Tarreaub4c84932013-07-23 19:15:30 +02006451 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006452 continue;
6453
6454 if (trule->act_prm.trk_ctr.table.n)
6455 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6456 else
6457 target = curproxy;
6458
6459 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006460 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6461 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreaud5ca9ab2013-05-28 17:40:25 +02006462 1 + tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006463 cfgerr++;
6464 }
6465 else if (target->table.size == 0) {
6466 Alert("Proxy '%s': table '%s' used but not configured.\n",
6467 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6468 cfgerr++;
6469 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006470 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6471 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6472 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 +02006473 1 + tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006474 cfgerr++;
6475 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006476 else {
6477 free(trule->act_prm.trk_ctr.table.n);
6478 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006479 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006480 * to pass a list of counters to track and allocate them right here using
6481 * stktable_alloc_data_type().
6482 */
6483 }
6484 }
6485
Emeric Brun32da3c42010-09-23 18:39:19 +02006486 if (curproxy->table.peers.name) {
6487 struct peers *curpeers = peers;
6488
6489 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6490 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6491 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006492 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006493 break;
6494 }
6495 }
6496
6497 if (!curpeers) {
6498 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6499 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006500 free((void *)curproxy->table.peers.name);
6501 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006502 cfgerr++;
6503 }
6504 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006505 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6506 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006507 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006508 cfgerr++;
6509 }
6510 }
6511
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006512 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006513 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006514 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6515 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6516 "proxy", curproxy->id);
6517 cfgerr++;
6518 goto out_uri_auth_compat;
6519 }
6520
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006521 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006522 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006523 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006524 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006525
Willy Tarreau95fa4692010-02-01 13:05:50 +01006526 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6527 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006528
6529 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006530 uri_auth_compat_req[i++] = "realm";
6531 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6532 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006533
Willy Tarreau95fa4692010-02-01 13:05:50 +01006534 uri_auth_compat_req[i++] = "unless";
6535 uri_auth_compat_req[i++] = "{";
6536 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6537 uri_auth_compat_req[i++] = "}";
6538 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006539
Willy Tarreauff011f22011-01-06 17:51:27 +01006540 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6541 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006542 cfgerr++;
6543 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006544 }
6545
Willy Tarreauff011f22011-01-06 17:51:27 +01006546 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006547
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006548 if (curproxy->uri_auth->auth_realm) {
6549 free(curproxy->uri_auth->auth_realm);
6550 curproxy->uri_auth->auth_realm = NULL;
6551 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006552
6553 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006554 }
6555out_uri_auth_compat:
6556
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006557 /* compile the log format */
6558 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006559 if (curproxy->conf.logformat_string != default_http_log_format &&
6560 curproxy->conf.logformat_string != default_tcp_log_format &&
6561 curproxy->conf.logformat_string != clf_http_log_format)
6562 free(curproxy->conf.logformat_string);
6563 curproxy->conf.logformat_string = NULL;
6564 free(curproxy->conf.lfs_file);
6565 curproxy->conf.lfs_file = NULL;
6566 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006567 }
6568
Willy Tarreau62a61232013-04-12 18:13:46 +02006569 if (curproxy->conf.logformat_string) {
6570 curproxy->conf.args.ctx = ARGC_LOG;
6571 curproxy->conf.args.file = curproxy->conf.lfs_file;
6572 curproxy->conf.args.line = curproxy->conf.lfs_line;
6573 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006574 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006575 curproxy->conf.args.file = NULL;
6576 curproxy->conf.args.line = 0;
6577 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006578
Willy Tarreau62a61232013-04-12 18:13:46 +02006579 if (curproxy->conf.uniqueid_format_string) {
6580 curproxy->conf.args.ctx = ARGC_UIF;
6581 curproxy->conf.args.file = curproxy->conf.uif_file;
6582 curproxy->conf.args.line = curproxy->conf.uif_line;
6583 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006584 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006585 curproxy->conf.args.file = NULL;
6586 curproxy->conf.args.line = 0;
6587 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006588
6589 /* only now we can check if some args remain unresolved */
6590 cfgerr += smp_resolve_args(curproxy);
6591 if (!cfgerr)
6592 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006593
Willy Tarreau2738a142006-07-08 17:28:09 +02006594 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006595 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006596 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006597 (!curproxy->timeout.connect ||
6598 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006599 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006600 " | While not properly invalid, you will certainly encounter various problems\n"
6601 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006602 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006604 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006605 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006606
Willy Tarreau1fa31262007-12-03 00:36:16 +01006607 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6608 * We must still support older configurations, so let's find out whether those
6609 * parameters have been set or must be copied from contimeouts.
6610 */
6611 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006612 if (!curproxy->timeout.tarpit ||
6613 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006614 /* tarpit timeout not set. We search in the following order:
6615 * default.tarpit, curr.connect, default.connect.
6616 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006617 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006618 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006619 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006620 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006621 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006622 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006623 }
6624 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006625 (!curproxy->timeout.queue ||
6626 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006627 /* queue timeout not set. We search in the following order:
6628 * default.queue, curr.connect, default.connect.
6629 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006630 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006631 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006632 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006633 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006634 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006635 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006636 }
6637 }
6638
Willy Tarreau1620ec32011-08-06 17:05:02 +02006639 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006640 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6641 curproxy->check_req = (char *)malloc(curproxy->check_len);
6642 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006643 }
6644
Willy Tarreau193b8c62012-11-22 00:17:38 +01006645 /* ensure that cookie capture length is not too large */
6646 if (curproxy->capture_len >= global.tune.cookie_len) {
6647 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6648 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6649 err_code |= ERR_WARN;
6650 curproxy->capture_len = global.tune.cookie_len - 1;
6651 }
6652
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006653 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006654 if (curproxy->nb_req_cap) {
6655 if (curproxy->mode == PR_MODE_HTTP) {
6656 curproxy->req_cap_pool = create_pool("ptrcap",
6657 curproxy->nb_req_cap * sizeof(char *),
6658 MEM_F_SHARED);
6659 } else {
6660 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6661 proxy_type_str(curproxy), curproxy->id);
6662 err_code |= ERR_WARN;
6663 curproxy->to_log &= ~LW_REQHDR;
6664 curproxy->nb_req_cap = 0;
6665 }
6666 }
6667
6668 if (curproxy->nb_rsp_cap) {
6669 if (curproxy->mode == PR_MODE_HTTP) {
6670 curproxy->rsp_cap_pool = create_pool("ptrcap",
6671 curproxy->nb_rsp_cap * sizeof(char *),
6672 MEM_F_SHARED);
6673 } else {
6674 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6675 proxy_type_str(curproxy), curproxy->id);
6676 err_code |= ERR_WARN;
6677 curproxy->to_log &= ~LW_REQHDR;
6678 curproxy->nb_rsp_cap = 0;
6679 }
6680 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006681
Willy Tarreaubaaee002006-06-26 02:48:02 +02006682 /* first, we will invert the servers list order */
6683 newsrv = NULL;
6684 while (curproxy->srv) {
6685 struct server *next;
6686
6687 next = curproxy->srv->next;
6688 curproxy->srv->next = newsrv;
6689 newsrv = curproxy->srv;
6690 if (!next)
6691 break;
6692 curproxy->srv = next;
6693 }
6694
Willy Tarreaudd701652010-05-25 23:03:02 +02006695 /* assign automatic UIDs to servers which don't have one yet */
6696 next_id = 1;
6697 newsrv = curproxy->srv;
6698 while (newsrv != NULL) {
6699 if (!newsrv->puid) {
6700 /* server ID not set, use automatic numbering with first
6701 * spare entry starting with next_svid.
6702 */
6703 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6704 newsrv->conf.id.key = newsrv->puid = next_id;
6705 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6706 }
6707 next_id++;
6708 newsrv = newsrv->next;
6709 }
6710
Willy Tarreau20697042007-11-15 23:26:18 +01006711 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006712 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713
Willy Tarreau62c3be22012-01-20 13:12:32 +01006714 /*
6715 * If this server supports a maxconn parameter, it needs a dedicated
6716 * tasks to fill the emptied slots when a connection leaves.
6717 * Also, resolve deferred tracking dependency if needed.
6718 */
6719 newsrv = curproxy->srv;
6720 while (newsrv != NULL) {
6721 if (newsrv->minconn > newsrv->maxconn) {
6722 /* Only 'minconn' was specified, or it was higher than or equal
6723 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6724 * this will avoid further useless expensive computations.
6725 */
6726 newsrv->maxconn = newsrv->minconn;
6727 } else if (newsrv->maxconn && !newsrv->minconn) {
6728 /* minconn was not specified, so we set it to maxconn */
6729 newsrv->minconn = newsrv->maxconn;
6730 }
6731
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006732#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006733 if (newsrv->use_ssl || newsrv->check.use_ssl)
6734 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006735#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006736
Willy Tarreau62c3be22012-01-20 13:12:32 +01006737 if (newsrv->trackit) {
6738 struct proxy *px;
6739 struct server *srv;
6740 char *pname, *sname;
6741
6742 pname = newsrv->trackit;
6743 sname = strrchr(pname, '/');
6744
6745 if (sname)
6746 *sname++ = '\0';
6747 else {
6748 sname = pname;
6749 pname = NULL;
6750 }
6751
6752 if (pname) {
6753 px = findproxy(pname, PR_CAP_BE);
6754 if (!px) {
6755 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6756 proxy_type_str(curproxy), curproxy->id,
6757 newsrv->id, pname);
6758 cfgerr++;
6759 goto next_srv;
6760 }
6761 } else
6762 px = curproxy;
6763
6764 srv = findserver(px, sname);
6765 if (!srv) {
6766 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6767 proxy_type_str(curproxy), curproxy->id,
6768 newsrv->id, sname);
6769 cfgerr++;
6770 goto next_srv;
6771 }
6772
6773 if (!(srv->state & SRV_CHECKED)) {
6774 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6775 "tracking as it does not have checks enabled.\n",
6776 proxy_type_str(curproxy), curproxy->id,
6777 newsrv->id, px->id, srv->id);
6778 cfgerr++;
6779 goto next_srv;
6780 }
6781
6782 if (curproxy != px &&
6783 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6784 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6785 "tracking: disable-on-404 option inconsistency.\n",
6786 proxy_type_str(curproxy), curproxy->id,
6787 newsrv->id, px->id, srv->id);
6788 cfgerr++;
6789 goto next_srv;
6790 }
6791
6792 /* if the other server is forced disabled, we have to do the same here */
6793 if (srv->state & SRV_MAINTAIN) {
6794 newsrv->state |= SRV_MAINTAIN;
6795 newsrv->state &= ~SRV_RUNNING;
6796 newsrv->health = 0;
6797 }
6798
6799 newsrv->track = srv;
6800 newsrv->tracknext = srv->tracknext;
6801 srv->tracknext = newsrv;
6802
6803 free(newsrv->trackit);
6804 newsrv->trackit = NULL;
6805 }
6806 next_srv:
6807 newsrv = newsrv->next;
6808 }
6809
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006810 /* We have to initialize the server lookup mechanism depending
6811 * on what LB algorithm was choosen.
6812 */
6813
6814 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6815 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6816 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006817 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6818 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6819 init_server_map(curproxy);
6820 } else {
6821 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6822 fwrr_init_server_groups(curproxy);
6823 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006824 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006825
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006826 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006827 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6828 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6829 fwlc_init_server_tree(curproxy);
6830 } else {
6831 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6832 fas_init_server_tree(curproxy);
6833 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006834 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006835
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006836 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006837 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6838 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6839 chash_init_server_tree(curproxy);
6840 } else {
6841 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6842 init_server_map(curproxy);
6843 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006844 break;
6845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006846
6847 if (curproxy->options & PR_O_LOGASAP)
6848 curproxy->to_log &= ~LW_BYTES;
6849
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006850 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006851 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006852 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6853 proxy_type_str(curproxy), curproxy->id);
6854 err_code |= ERR_WARN;
6855 }
6856
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006857 if (curproxy->mode != PR_MODE_HTTP) {
6858 int optnum;
6859
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006860 if (curproxy->uri_auth) {
6861 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6862 proxy_type_str(curproxy), curproxy->id);
6863 err_code |= ERR_WARN;
6864 curproxy->uri_auth = NULL;
6865 }
6866
Willy Tarreau87cf5142011-08-19 22:57:24 +02006867 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006868 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6869 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6870 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006871 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006872 }
6873
6874 if (curproxy->options & PR_O_ORGTO) {
6875 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6876 "originalto", proxy_type_str(curproxy), curproxy->id);
6877 err_code |= ERR_WARN;
6878 curproxy->options &= ~PR_O_ORGTO;
6879 }
6880
6881 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6882 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6883 (curproxy->cap & cfg_opts[optnum].cap) &&
6884 (curproxy->options & cfg_opts[optnum].val)) {
6885 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6886 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6887 err_code |= ERR_WARN;
6888 curproxy->options &= ~cfg_opts[optnum].val;
6889 }
6890 }
6891
6892 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6893 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6894 (curproxy->cap & cfg_opts2[optnum].cap) &&
6895 (curproxy->options2 & cfg_opts2[optnum].val)) {
6896 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6897 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6898 err_code |= ERR_WARN;
6899 curproxy->options2 &= ~cfg_opts2[optnum].val;
6900 }
6901 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006902
Pieter Baauwd551fb52013-05-08 22:49:23 +02006903#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006904 if (curproxy->conn_src.bind_hdr_occ) {
6905 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006906 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006907 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006908 err_code |= ERR_WARN;
6909 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006910#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006911 }
6912
Willy Tarreaubaaee002006-06-26 02:48:02 +02006913 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006914 * ensure that we're not cross-dressing a TCP server into HTTP.
6915 */
6916 newsrv = curproxy->srv;
6917 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006918 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006919 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6920 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006921 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006922 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006923
Willy Tarreau0cec3312011-10-31 13:49:26 +01006924 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6925 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6926 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6927 err_code |= ERR_WARN;
6928 }
6929
Willy Tarreau82ffa392013-08-13 17:19:08 +02006930 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
6931 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6932 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6933 err_code |= ERR_WARN;
6934 }
6935
Pieter Baauwd551fb52013-05-08 22:49:23 +02006936#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006937 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6938 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006939 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 +01006940 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006941 err_code |= ERR_WARN;
6942 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006943#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006944 newsrv = newsrv->next;
6945 }
6946
Willy Tarreauc1a21672009-08-16 22:37:44 +02006947 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006948 if (!curproxy->accept)
6949 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006950
Willy Tarreauc1a21672009-08-16 22:37:44 +02006951 if (curproxy->tcp_req.inspect_delay ||
6952 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006953 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006954
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006955 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006956 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006957 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006958 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006959
6960 /* both TCP and HTTP must check switching rules */
6961 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6962 }
6963
6964 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006965 if (curproxy->tcp_req.inspect_delay ||
6966 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6967 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6968
Emeric Brun97679e72010-09-23 17:56:44 +02006969 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6970 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6971
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006972 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006973 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006974 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006975 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006976
6977 /* If the backend does requires RDP cookie persistence, we have to
6978 * enable the corresponding analyser.
6979 */
6980 if (curproxy->options2 & PR_O2_RDPC_PRST)
6981 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6982 }
6983
Emeric Brunc52962f2012-11-15 18:28:02 +01006984#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006985 /* Configure SSL for each bind line.
6986 * Note: if configuration fails at some point, the ->ctx member
6987 * remains NULL so that listeners can later detach.
6988 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006989 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006990 if (!bind_conf->is_ssl) {
6991 if (bind_conf->default_ctx) {
6992 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6993 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6994 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006995 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006996 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006997 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006998 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006999 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007000 cfgerr++;
7001 continue;
7002 }
7003
Emeric Brun4b3091e2012-09-24 15:48:52 +02007004 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007005 Alert("Unable to allocate SSL session cache.\n");
7006 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007007 continue;
7008 }
7009
Emeric Brunfc0421f2012-09-07 17:30:07 +02007010 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007011 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007012 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007013#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007014
Willy Tarreaue6b98942007-10-29 01:09:36 +01007015 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007016 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007017 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007018 if (!listener->luid) {
7019 /* listener ID not set, use automatic numbering with first
7020 * spare entry starting with next_luid.
7021 */
7022 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7023 listener->conf.id.key = listener->luid = next_id;
7024 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007025 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007026 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007027
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007028 /* enable separate counters */
7029 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7030 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007031 if (!listener->name)
7032 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007033 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007034
Willy Tarreaue6b98942007-10-29 01:09:36 +01007035 if (curproxy->options & PR_O_TCP_NOLING)
7036 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007037 if (!listener->maxconn)
7038 listener->maxconn = curproxy->maxconn;
7039 if (!listener->backlog)
7040 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007041 if (!listener->maxaccept)
7042 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7043
7044 /* we want to have an optimal behaviour on single process mode to
7045 * maximize the work at once, but in multi-process we want to keep
7046 * some fairness between processes, so we target half of the max
7047 * number of events to be balanced over all the processes the proxy
7048 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7049 * used to disable the limit.
7050 */
7051 if (listener->maxaccept > 0) {
7052 if (nbproc > 1)
7053 listener->maxaccept = (listener->maxaccept + 1) / 2;
7054 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7055 }
7056
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007057 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007058 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007059 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007060 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007061
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007062 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7063 listener->options |= LI_O_TCP_RULES;
7064
Willy Tarreaude3041d2010-05-31 10:56:17 +02007065 if (curproxy->mon_mask.s_addr)
7066 listener->options |= LI_O_CHK_MONNET;
7067
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007068 /* smart accept mode is automatic in HTTP mode */
7069 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007070 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007071 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7072 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007073 }
7074
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007075 /* Release unused SSL configs */
7076 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7077 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007078 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007079#ifdef USE_OPENSSL
7080 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007081 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007082 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007083 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007084 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007085#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007086 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007087
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007088 /* Check multi-process mode compatibility for the current proxy */
7089 if (global.nbproc > 1) {
7090 int nbproc = 0;
7091 if (curproxy->bind_proc) {
7092 int proc;
7093 for (proc = 0; proc < global.nbproc; proc++) {
7094 if (curproxy->bind_proc & (1 << proc)) {
7095 nbproc++;
7096 }
7097 }
7098 } else {
7099 nbproc = global.nbproc;
7100 }
7101 if (curproxy->table.peers.name) {
7102 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7103 curproxy->id);
7104 cfgerr++;
7105 }
7106 if (nbproc > 1) {
7107 if (curproxy->uri_auth) {
7108 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7109 curproxy->id);
7110 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7111 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7112 curproxy->id);
7113 }
7114 }
7115 if (curproxy->appsession_name) {
7116 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7117 curproxy->id);
7118 }
7119 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7120 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7121 curproxy->id);
7122 }
7123 }
7124 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007125
7126 /* create the task associated with the proxy */
7127 curproxy->task = task_new();
7128 if (curproxy->task) {
7129 curproxy->task->context = curproxy;
7130 curproxy->task->process = manage_proxy;
7131 /* no need to queue, it will be done automatically if some
7132 * listener gets limited.
7133 */
7134 curproxy->task->expire = TICK_ETERNITY;
7135 } else {
7136 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7137 curproxy->id);
7138 cfgerr++;
7139 }
7140
Willy Tarreaubaaee002006-06-26 02:48:02 +02007141 curproxy = curproxy->next;
7142 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007143
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007144 /* Check multi-process mode compatibility */
7145 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007146 if (global.stats_fe && !global.stats_fe->bind_proc) {
7147 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 +01007148 }
7149 }
7150
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007151 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7152 struct auth_users *curuser;
7153 int g;
7154
7155 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7156 unsigned int group_mask = 0;
7157 char *group = NULL;
7158
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007159 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007160 continue;
7161
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007162 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007163
7164 for (g = 0; g < curuserlist->grpcnt; g++)
7165 if (!strcmp(curuserlist->groups[g], group))
7166 break;
7167
7168 if (g == curuserlist->grpcnt) {
7169 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7170 curuserlist->name, group, curuser->user);
7171 err_code |= ERR_ALERT | ERR_FATAL;
7172 goto out;
7173 }
7174
7175 group_mask |= (1 << g);
7176 }
7177
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007178 free(curuser->u.groups);
7179 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007180 }
7181
7182 for (g = 0; g < curuserlist->grpcnt; g++) {
7183 char *user = NULL;
7184
7185 if (!curuserlist->groupusers[g])
7186 continue;
7187
7188 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7189 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7190 if (!strcmp(curuser->user, user))
7191 break;
7192
7193 if (!curuser) {
7194 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7195 curuserlist->name, user, curuserlist->groups[g]);
7196 err_code |= ERR_ALERT | ERR_FATAL;
7197 goto out;
7198 }
7199
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007200 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007201 }
7202
7203 free(curuserlist->groupusers[g]);
7204 }
7205
7206 free(curuserlist->groupusers);
7207
7208#ifdef DEBUG_AUTH
7209 for (g = 0; g < curuserlist->grpcnt; g++) {
7210 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7211
7212 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007213 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007214 fprintf(stderr, " %s", curuser->user);
7215 }
7216
7217 fprintf(stderr, "\n");
7218 }
7219#endif
7220
Willy Tarreaufbb78422011-06-05 15:38:35 +02007221 }
7222
7223 /* automatically compute fullconn if not set. We must not do it in the
7224 * loop above because cross-references are not yet fully resolved.
7225 */
7226 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7227 /* If <fullconn> is not set, let's set it to 10% of the sum of
7228 * the possible incoming frontend's maxconns.
7229 */
7230 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7231 struct proxy *fe;
7232 int total = 0;
7233
7234 /* sum up the number of maxconns of frontends which
7235 * reference this backend at least once or which are
7236 * the same one ('listen').
7237 */
7238 for (fe = proxy; fe; fe = fe->next) {
7239 struct switching_rule *rule;
7240 struct hdr_exp *exp;
7241 int found = 0;
7242
7243 if (!(fe->cap & PR_CAP_FE))
7244 continue;
7245
7246 if (fe == curproxy) /* we're on a "listen" instance */
7247 found = 1;
7248
7249 if (fe->defbe.be == curproxy) /* "default_backend" */
7250 found = 1;
7251
7252 /* check if a "use_backend" rule matches */
7253 if (!found) {
7254 list_for_each_entry(rule, &fe->switching_rules, list) {
7255 if (rule->be.backend == curproxy) {
7256 found = 1;
7257 break;
7258 }
7259 }
7260 }
7261
7262 /* check if a "reqsetbe" rule matches */
7263 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7264 if (exp->action == ACT_SETBE &&
7265 (struct proxy *)exp->replace == curproxy) {
7266 found = 1;
7267 break;
7268 }
7269 }
7270
7271 /* now we've checked all possible ways to reference a backend
7272 * from a frontend.
7273 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007274 if (!found)
7275 continue;
7276 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007277 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007278 /* we have the sum of the maxconns in <total>. We only
7279 * keep 10% of that sum to set the default fullconn, with
7280 * a hard minimum of 1 (to avoid a divide by zero).
7281 */
7282 curproxy->fullconn = (total + 9) / 10;
7283 if (!curproxy->fullconn)
7284 curproxy->fullconn = 1;
7285 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007286 }
7287
Willy Tarreau056f5682010-06-06 15:51:11 +02007288 /* initialize stick-tables on backend capable proxies. This must not
7289 * be done earlier because the data size may be discovered while parsing
7290 * other proxies.
7291 */
7292 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007293 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007294
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007295 /*
7296 * Recount currently required checks.
7297 */
7298
7299 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7300 int optnum;
7301
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007302 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7303 if (curproxy->options & cfg_opts[optnum].val)
7304 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007305
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007306 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7307 if (curproxy->options2 & cfg_opts2[optnum].val)
7308 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007309 }
7310
Willy Tarreau122541c2011-09-07 21:24:49 +02007311 if (peers) {
7312 struct peers *curpeers = peers, **last;
7313 struct peer *p, *pb;
7314
7315 /* Remove all peers sections which don't have a valid listener.
7316 * This can happen when a peers section is never referenced and
7317 * does not contain a local peer.
7318 */
7319 last = &peers;
7320 while (*last) {
7321 curpeers = *last;
7322 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007323 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007324 last = &curpeers->next;
7325 continue;
7326 }
7327
7328 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7329 curpeers->id, localpeer);
7330
7331 p = curpeers->remote;
7332 while (p) {
7333 pb = p->next;
7334 free(p->id);
7335 free(p);
7336 p = pb;
7337 }
7338
7339 /* Destroy and unlink this curpeers section.
7340 * Note: curpeers is backed up into *last.
7341 */
7342 free(curpeers->id);
7343 curpeers = curpeers->next;
7344 free(*last);
7345 *last = curpeers;
7346 }
7347 }
7348
Willy Tarreau34eb6712011-10-24 18:15:04 +02007349 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007350 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007351 MEM_F_SHARED);
7352
Willy Tarreaubb925012009-07-23 13:36:36 +02007353 if (cfgerr > 0)
7354 err_code |= ERR_ALERT | ERR_FATAL;
7355 out:
7356 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007357}
7358
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007359/*
7360 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7361 * parsing sessions.
7362 */
7363void cfg_register_keywords(struct cfg_kw_list *kwl)
7364{
7365 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7366}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007367
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007368/*
7369 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7370 */
7371void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7372{
7373 LIST_DEL(&kwl->list);
7374 LIST_INIT(&kwl->list);
7375}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007376
7377/*
7378 * Local variables:
7379 * c-indent-level: 8
7380 * c-basic-offset: 8
7381 * End:
7382 */