blob: c31774320235b5a210982bc4d15533801c5193e1 [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) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
275 l->fd = -1;
276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200594#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 else if (!strcmp(args[0], "tune.bufsize")) {
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.bufsize = atol(args[1]);
602 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
603 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100604 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200605 }
606 else if (!strcmp(args[0], "tune.maxrewrite")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.maxrewrite = atol(args[1]);
613 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
614 global.tune.maxrewrite = global.tune.bufsize / 2;
615 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100616 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
617 if (global.tune.client_rcvbuf != 0) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.client_rcvbuf = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
630 if (global.tune.server_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.server_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.sndbuf.client")) {
643 if (global.tune.client_sndbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.client_sndbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.server")) {
656 if (global.tune.server_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.server_sndbuf = atol(args[1]);
667 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200668 else if (!strcmp(args[0], "tune.pipesize")) {
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.pipesize = atol(args[1]);
675 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100676 else if (!strcmp(args[0], "tune.http.cookielen")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.cookie_len = atol(args[1]) + 1;
683 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200684 else if (!strcmp(args[0], "tune.http.maxhdr")) {
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 global.tune.max_http_hdr = atol(args[1]);
691 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100692 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
693#ifdef USE_ZLIB
694 if (*args[1]) {
695 global.tune.zlibmemlevel = atoi(args[1]);
696 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
697 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
698 file, linenum, args[0]);
699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
701 }
702 } else {
703 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
704 file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707 }
708#else
709 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712#endif
713 }
714 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
715#ifdef USE_ZLIB
716 if (*args[1]) {
717 global.tune.zlibwindowsize = atoi(args[1]);
718 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
719 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
720 file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 } else {
725 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
726 file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730#else
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734#endif
735 }
William Lallemandf3747832012-11-09 12:33:10 +0100736 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
737 if (*args[1]) {
738 global.tune.comp_maxlevel = atoi(args[1]);
739 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
740 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
741 file, linenum, args[0]);
742 err_code |= ERR_ALERT | ERR_FATAL;
743 goto out;
744 }
745 } else {
746 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
747 file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 else if (!strcmp(args[0], "uid")) {
753 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200754 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.uid = atol(args[1]);
764 }
765 else if (!strcmp(args[0], "gid")) {
766 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200767 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 global.gid = atol(args[1]);
777 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200778 /* user/group name handling */
779 else if (!strcmp(args[0], "user")) {
780 struct passwd *ha_user;
781 if (global.uid != 0) {
782 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200785 }
786 errno = 0;
787 ha_user = getpwnam(args[1]);
788 if (ha_user != NULL) {
789 global.uid = (int)ha_user->pw_uid;
790 }
791 else {
792 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 +0200793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 }
796 else if (!strcmp(args[0], "group")) {
797 struct group *ha_group;
798 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200799 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200802 }
803 errno = 0;
804 ha_group = getgrnam(args[1]);
805 if (ha_group != NULL) {
806 global.gid = (int)ha_group->gr_gid;
807 }
808 else {
809 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 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 }
813 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 global.nbproc = atol(args[1]);
821 }
822 else if (!strcmp(args[0], "maxconn")) {
823 if (global.maxconn != 0) {
824 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200825 err_code |= ERR_ALERT;
826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 global.maxconn = atol(args[1]);
834#ifdef SYSTEM_MAXCONN
835 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
836 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);
837 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200839 }
840#endif /* SYSTEM_MAXCONN */
841 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200842 else if (!strcmp(args[0], "maxsslconn")) {
843#ifdef USE_OPENSSL
844 if (*(args[1]) == 0) {
845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849 global.maxsslconn = atol(args[1]);
850#else
Emeric Brun0914df82012-10-02 18:45:42 +0200851 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200854#endif
855 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200856 else if (!strcmp(args[0], "maxconnrate")) {
857 if (global.cps_lim != 0) {
858 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT;
860 goto out;
861 }
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.cps_lim = atol(args[1]);
868 }
William Lallemandd85f9172012-11-09 17:05:39 +0100869 else if (!strcmp(args[0], "maxcomprate")) {
870 if (*(args[1]) == 0) {
871 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 global.comp_rate_lim = atoi(args[1]) * 1024;
876 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100877 else if (!strcmp(args[0], "maxpipes")) {
878 if (global.maxpipes != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200880 err_code |= ERR_ALERT;
881 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100887 }
888 global.maxpipes = atol(args[1]);
889 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100890 else if (!strcmp(args[0], "maxzlibmem")) {
891 if (*(args[1]) == 0) {
892 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
William Lallemande3a7d992012-11-20 11:25:20 +0100896 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100897 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100898 else if (!strcmp(args[0], "maxcompcpuusage")) {
899 if (*(args[1]) == 0) {
900 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 compress_min_idle = 100 - atoi(args[1]);
905 if (compress_min_idle < 0 || compress_min_idle > 100) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910}
911
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912 else if (!strcmp(args[0], "ulimit-n")) {
913 if (global.rlimit_nofile != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 global.rlimit_nofile = atol(args[1]);
924 }
925 else if (!strcmp(args[0], "chroot")) {
926 if (global.chroot != NULL) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.chroot = strdup(args[1]);
937 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200938 else if (!strcmp(args[0], "description")) {
939 int i, len=0;
940 char *d;
941
942 if (!*args[1]) {
943 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
944 file, linenum, args[0]);
945 err_code |= ERR_ALERT | ERR_FATAL;
946 goto out;
947 }
948
949 for(i=1; *args[i]; i++)
950 len += strlen(args[i])+1;
951
952 if (global.desc)
953 free(global.desc);
954
955 global.desc = d = (char *)calloc(1, len);
956
957 d += sprintf(d, "%s", args[1]);
958 for(i=2; *args[i]; i++)
959 d += sprintf(d, " %s", args[i]);
960 }
961 else if (!strcmp(args[0], "node")) {
962 int i;
963 char c;
964
965 for (i=0; args[1][i]; i++) {
966 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100967 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
968 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200969 break;
970 }
971
972 if (!i || args[1][i]) {
973 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
974 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
975 file, linenum, args[0]);
976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
978 }
979
980 if (global.node)
981 free(global.node);
982
983 global.node = strdup(args[1]);
984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 else if (!strcmp(args[0], "pidfile")) {
986 if (global.pidfile != NULL) {
987 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
991 if (*(args[1]) == 0) {
992 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200993 err_code |= ERR_ALERT | ERR_FATAL;
994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 }
996 global.pidfile = strdup(args[1]);
997 }
Emeric Bruned760922010-10-22 17:59:25 +0200998 else if (!strcmp(args[0], "unix-bind")) {
999 int cur_arg = 1;
1000 while (*(args[cur_arg])) {
1001 if (!strcmp(args[cur_arg], "prefix")) {
1002 if (global.unix_bind.prefix != NULL) {
1003 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1004 err_code |= ERR_ALERT;
1005 cur_arg += 2;
1006 continue;
1007 }
1008
1009 if (*(args[cur_arg+1]) == 0) {
1010 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1015 cur_arg += 2;
1016 continue;
1017 }
1018
1019 if (!strcmp(args[cur_arg], "mode")) {
1020
1021 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1022 cur_arg += 2;
1023 continue;
1024 }
1025
1026 if (!strcmp(args[cur_arg], "uid")) {
1027
1028 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1029 cur_arg += 2;
1030 continue;
1031 }
1032
1033 if (!strcmp(args[cur_arg], "gid")) {
1034
1035 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1036 cur_arg += 2;
1037 continue;
1038 }
1039
1040 if (!strcmp(args[cur_arg], "user")) {
1041 struct passwd *user;
1042
1043 user = getpwnam(args[cur_arg + 1]);
1044 if (!user) {
1045 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1046 file, linenum, args[0], args[cur_arg + 1 ]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 global.unix_bind.ux.uid = user->pw_uid;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (!strcmp(args[cur_arg], "group")) {
1057 struct group *group;
1058
1059 group = getgrnam(args[cur_arg + 1]);
1060 if (!group) {
1061 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1062 file, linenum, args[0], args[cur_arg + 1 ]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 global.unix_bind.ux.gid = group->gr_gid;
1068 cur_arg += 2;
1069 continue;
1070 }
1071
Willy Tarreaub48f9582011-09-05 01:17:06 +02001072 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001073 file, linenum, args[0]);
1074 err_code |= ERR_ALERT | ERR_FATAL;
1075 goto out;
1076 }
1077 }
William Lallemand0f99e342011-10-12 17:50:54 +02001078 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1079 /* delete previous herited or defined syslog servers */
1080 struct logsrv *back;
1081 struct logsrv *tmp;
1082
1083 if (*(args[1]) != 0) {
1084 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088
1089 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1090 LIST_DEL(&tmp->list);
1091 free(tmp);
1092 }
1093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001095 struct logsrv *logsrv;
1096
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 if (*(args[1]) == 0 || *(args[2]) == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
William Lallemand0f99e342011-10-12 17:50:54 +02001102
1103 logsrv = calloc(1, sizeof(struct logsrv));
1104
1105 logsrv->facility = get_log_facility(args[2]);
1106 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111
William Lallemand0f99e342011-10-12 17:50:54 +02001112 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->level = get_log_level(args[3]);
1115 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 }
1120 }
1121
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001123 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001124 logsrv->minlvl = get_log_level(args[4]);
1125 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001126 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001129 }
1130 }
1131
Robert Tsai81ae1952007-12-05 10:47:29 +01001132 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001133 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001134 if (!sk) {
1135 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001136 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001137 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001138 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001139 goto out;
1140 }
William Lallemand0f99e342011-10-12 17:50:54 +02001141 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001142 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001143 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001144 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001145 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1146 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001147 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001148 goto out;
1149 }
William Lallemand0f99e342011-10-12 17:50:54 +02001150 logsrv->addr = *sk;
1151 if (!get_host_port(&logsrv->addr))
1152 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154
William Lallemand0f99e342011-10-12 17:50:54 +02001155 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001156 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001157 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1158 char *name;
1159 int len;
1160
1161 if (global.log_send_hostname != NULL) {
1162 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1163 err_code |= ERR_ALERT;
1164 goto out;
1165 }
1166
1167 if (*(args[1]))
1168 name = args[1];
1169 else
1170 name = hostname;
1171
1172 len = strlen(name);
1173
1174 /* We'll add a space after the name to respect the log format */
1175 free(global.log_send_hostname);
1176 global.log_send_hostname = malloc(len + 2);
1177 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1178 }
Kevinm48936af2010-12-22 16:08:21 +00001179 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1180 if (*(args[1]) == 0) {
1181 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185 free(global.log_tag);
1186 global.log_tag = strdup(args[1]);
1187 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001188 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1189 if (global.spread_checks != 0) {
1190 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001191 err_code |= ERR_ALERT;
1192 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
1194 if (*(args[1]) == 0) {
1195 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001198 }
1199 global.spread_checks = atol(args[1]);
1200 if (global.spread_checks < 0 || global.spread_checks > 50) {
1201 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001204 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001205 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1206#ifdef USE_CPU_AFFINITY
1207 int cur_arg, i;
1208 unsigned int proc = 0;
1209 unsigned long cpus = 0;
1210
1211 if (strcmp(args[1], "all") == 0)
1212 proc = 0xFFFFFFFF;
1213 else if (strcmp(args[1], "odd") == 0)
1214 proc = 0x55555555;
1215 else if (strcmp(args[1], "even") == 0)
1216 proc = 0xAAAAAAAA;
1217 else {
1218 proc = atoi(args[1]);
1219 if (proc >= 1 && proc <= 32)
1220 proc = 1 << (proc - 1);
1221 }
1222
1223 if (!proc || !*args[2]) {
1224 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",
1225 file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 cur_arg = 2;
1231 while (*args[cur_arg]) {
1232 unsigned int low, high;
1233
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001234 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001235 char *dash = strchr(args[cur_arg], '-');
1236
1237 low = high = str2uic(args[cur_arg]);
1238 if (dash)
1239 high = str2uic(dash + 1);
1240
1241 if (high < low) {
1242 unsigned int swap = low;
1243 low = high;
1244 high = swap;
1245 }
1246
1247 if (low < 0 || high >= sizeof(long) * 8) {
1248 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1249 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
1254 while (low <= high)
1255 cpus |= 1UL << low++;
1256 }
1257 else {
1258 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1259 file, linenum, args[0], args[cur_arg]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263 cur_arg++;
1264 }
1265 for (i = 0; i < 32; i++)
1266 if (proc & (1 << i))
1267 global.cpu_map[i] = cpus;
1268#else
1269 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1270 err_code |= ERR_ALERT | ERR_FATAL;
1271 goto out;
1272#endif
1273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001274 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001275 struct cfg_kw_list *kwl;
1276 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001277 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001278
1279 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1280 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1281 if (kwl->kw[index].section != CFG_GLOBAL)
1282 continue;
1283 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001284 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001285 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001286 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001289 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001290 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001291 err_code |= ERR_WARN;
1292 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001293 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001294 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001295 }
1296 }
1297 }
1298
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001302
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001304 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306}
1307
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001308void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001310 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 defproxy.mode = PR_MODE_TCP;
1312 defproxy.state = PR_STNEW;
1313 defproxy.maxconn = cfg_maxpconn;
1314 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315
1316 defproxy.defsrv.inter = DEF_CHKINTR;
1317 defproxy.defsrv.fastinter = 0;
1318 defproxy.defsrv.downinter = 0;
1319 defproxy.defsrv.rise = DEF_RISETIME;
1320 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001321 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001322 defproxy.defsrv.maxqueue = 0;
1323 defproxy.defsrv.minconn = 0;
1324 defproxy.defsrv.maxconn = 0;
1325 defproxy.defsrv.slowstart = 0;
1326 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1327 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1328 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329}
1330
Willy Tarreauade5ec42010-01-28 19:33:49 +01001331
1332static int create_cond_regex_rule(const char *file, int line,
1333 struct proxy *px, int dir, int action, int flags,
1334 const char *cmd, const char *reg, const char *repl,
1335 const char **cond_start)
1336{
1337 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001338 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001339 const char *err;
1340 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001341 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001342
1343 if (px == &defproxy) {
1344 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto err;
1347 }
1348
1349 if (*reg == 0) {
1350 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1351 err_code |= ERR_ALERT | ERR_FATAL;
1352 goto err;
1353 }
1354
1355 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1356 err_code |= ERR_WARN;
1357
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 if (cond_start &&
1359 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001360 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1361 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1362 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366 }
1367 else if (cond_start && **cond_start) {
1368 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1369 file, line, cmd, *cond_start);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto err;
1372 }
1373
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001374 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001376 else
1377 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001378
Willy Tarreauade5ec42010-01-28 19:33:49 +01001379 preg = calloc(1, sizeof(regex_t));
1380 if (!preg) {
1381 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1382 err_code = ERR_ALERT | ERR_FATAL;
1383 goto err;
1384 }
1385
1386 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1387 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1388 err_code = ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001392 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001393 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 if (repl && err) {
1395 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1396 file, line, cmd, *err);
1397 err_code |= ERR_ALERT | ERR_FATAL;
1398 goto err;
1399 }
1400
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001401 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001402 err_code |= ERR_WARN;
1403
Willy Tarreauf4068b62012-05-08 17:37:49 +02001404 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001405 return err_code;
1406 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001407 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001408 free(preg);
1409 return err_code;
1410}
1411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001414 * Returns the error code, 0 if OK, or any combination of :
1415 * - ERR_ABORT: must abort ASAP
1416 * - ERR_FATAL: we can continue parsing but not start the service
1417 * - ERR_WARN: a warning has been emitted
1418 * - ERR_ALERT: an alert has been emitted
1419 * Only the two first ones can stop processing, the two others are just
1420 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001422int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1423{
1424 static struct peers *curpeers = NULL;
1425 struct peer *newpeer = NULL;
1426 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001427 struct bind_conf *bind_conf;
1428 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001429 int err_code = 0;
1430
1431 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1432
1433 err = invalid_char(args[1]);
1434 if (err) {
1435 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1436 file, linenum, *err, args[0], args[1]);
1437 err_code |= ERR_ALERT | ERR_FATAL;
1438 }
1439
1440 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1441 /*
1442 * If there are two proxies with the same name only following
1443 * combinations are allowed:
1444 */
1445 if (strcmp(curpeers->id, args[1]) == 0) {
1446 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1447 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1448 err_code |= ERR_WARN;
1449 }
1450 }
1451
1452 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1453 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1454 err_code |= ERR_ALERT | ERR_ABORT;
1455 goto out;
1456 }
1457
1458 curpeers->next = peers;
1459 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001460 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001461 curpeers->conf.line = linenum;
1462 curpeers->last_change = now.tv_sec;
1463 curpeers->id = strdup(args[1]);
1464 }
1465 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1466 char *rport, *raddr;
1467 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001468 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001469 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001470
1471 if (!*args[2]) {
1472 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1473 file, linenum, args[0]);
1474 err_code |= ERR_ALERT | ERR_FATAL;
1475 goto out;
1476 }
1477
1478 err = invalid_char(args[1]);
1479 if (err) {
1480 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1481 file, linenum, *err, args[1]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1487 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1488 err_code |= ERR_ALERT | ERR_ABORT;
1489 goto out;
1490 }
1491
1492 /* the peers are linked backwards first */
1493 curpeers->count++;
1494 newpeer->next = curpeers->remote;
1495 curpeers->remote = newpeer;
1496 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001497 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001498 newpeer->conf.line = linenum;
1499
1500 newpeer->last_change = now.tv_sec;
1501 newpeer->id = strdup(args[1]);
1502
1503 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001504 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001505 if (rport) {
1506 *rport++ = 0;
1507 realport = atol(rport);
1508 }
1509 if (!realport) {
1510 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
Willy Tarreaufab5a432011-03-04 15:31:53 +01001515 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001516 free(raddr);
1517 if (!sk) {
1518 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001523 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001524 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001525 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001526
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001527 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001528 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1529 file, linenum, newpeer->addr.ss_family, args[2]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001534 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001535
1536 if (strcmp(newpeer->id, localpeer) == 0) {
1537 /* Current is local peer, it define a frontend */
1538 newpeer->local = 1;
1539
1540 if (!curpeers->peers_fe) {
1541 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1543 err_code |= ERR_ALERT | ERR_ABORT;
1544 goto out;
1545 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001546
Willy Tarreau237250c2011-07-29 01:49:03 +02001547 init_new_proxy(curpeers->peers_fe);
1548 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 curpeers->peers_fe->last_change = now.tv_sec;
1551 curpeers->peers_fe->id = strdup(args[1]);
1552 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001553 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1555 curpeers->peers_fe->timeout.connect = 5000;
1556 curpeers->peers_fe->accept = peer_accept;
1557 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558
1559 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1560
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001561 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1562 if (err_msg && *err_msg) {
1563 indent_msg(&err_msg, 2);
1564 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1565 }
1566 else
1567 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1568 file, linenum, args[0], args[1], args[2]);
1569 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 err_code |= ERR_FATAL;
1571 goto out;
1572 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573
1574 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1575 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1576 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1577 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1578 l->accept = session_accept;
1579 l->handler = process_session;
1580 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1581 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1582 global.maxsock += l->maxconn;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 }
1585 }
1586 } /* neither "peer" nor "peers" */
1587 else if (*args[0] != 0) {
1588 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
1591 }
1592
1593out:
1594 return err_code;
1595}
1596
1597
Willy Tarreau3842f002009-06-14 11:39:52 +02001598int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599{
1600 static struct proxy *curproxy = NULL;
1601 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001602 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001603 int rc;
1604 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001605 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001606 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001607 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001608 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001609 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610
Willy Tarreau977b8e42006-12-29 14:19:17 +01001611 if (!strcmp(args[0], "listen"))
1612 rc = PR_CAP_LISTEN;
1613 else if (!strcmp(args[0], "frontend"))
1614 rc = PR_CAP_FE | PR_CAP_RS;
1615 else if (!strcmp(args[0], "backend"))
1616 rc = PR_CAP_BE | PR_CAP_RS;
1617 else if (!strcmp(args[0], "ruleset"))
1618 rc = PR_CAP_RS;
1619 else
1620 rc = PR_CAP_NONE;
1621
1622 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 if (!*args[1]) {
1624 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1625 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_ABORT;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001630
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001631 err = invalid_char(args[1]);
1632 if (err) {
1633 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1634 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001636 }
1637
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001638 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1639 /*
1640 * If there are two proxies with the same name only following
1641 * combinations are allowed:
1642 *
1643 * listen backend frontend ruleset
1644 * listen - - - -
1645 * backend - - OK -
1646 * frontend - OK - -
1647 * ruleset - - - -
1648 */
1649
1650 if (!strcmp(curproxy->id, args[1]) &&
1651 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1652 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001653 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1654 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1655 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001656 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001657 }
1658 }
1659
Willy Tarreaubaaee002006-06-26 02:48:02 +02001660 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1661 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_ABORT;
1663 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001665
Willy Tarreau97cb7802010-01-03 20:23:58 +01001666 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 curproxy->next = proxy;
1668 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001669 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001670 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001671 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674
1675 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001677 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001678 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001679
Willy Tarreau4348fad2012-09-20 16:48:07 +02001680 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1681
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001682 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1683 if (err_msg && *err_msg) {
1684 indent_msg(&err_msg, 2);
1685 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1686 }
1687 else
1688 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1689 file, linenum, args[0], args[1], args[2]);
1690 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_FATAL;
1692 goto out;
1693 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001694
Willy Tarreau4348fad2012-09-20 16:48:07 +02001695 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001696 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 }
1699
1700 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001701 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001702 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001703
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001706 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001707 curproxy->no_options = defproxy.no_options;
1708 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001709 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001710 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001711 curproxy->except_net = defproxy.except_net;
1712 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001713 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001714 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001716 if (defproxy.fwdfor_hdr_len) {
1717 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1718 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1719 }
1720
Willy Tarreaub86db342009-11-30 11:50:16 +01001721 if (defproxy.orgto_hdr_len) {
1722 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1723 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1724 }
1725
Mark Lamourinec2247f02012-01-04 13:02:01 -05001726 if (defproxy.server_id_hdr_len) {
1727 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1728 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1729 }
1730
Willy Tarreau977b8e42006-12-29 14:19:17 +01001731 if (curproxy->cap & PR_CAP_FE) {
1732 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001733 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001734 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
1736 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001737 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1738 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
1740 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (curproxy->cap & PR_CAP_BE) {
1744 curproxy->fullconn = defproxy.fullconn;
1745 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001747 if (defproxy.check_req) {
1748 curproxy->check_req = calloc(1, defproxy.check_len);
1749 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1750 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001751 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001753 if (defproxy.expect_str) {
1754 curproxy->expect_str = strdup(defproxy.expect_str);
1755 if (defproxy.expect_regex) {
1756 /* note: this regex is known to be valid */
1757 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1758 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1759 }
1760 }
1761
Willy Tarreau67402132012-05-31 20:40:20 +02001762 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001763 if (defproxy.cookie_name)
1764 curproxy->cookie_name = strdup(defproxy.cookie_name);
1765 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001766 if (defproxy.cookie_domain)
1767 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001768
Willy Tarreau31936852010-10-06 16:59:56 +02001769 if (defproxy.cookie_maxidle)
1770 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1771
1772 if (defproxy.cookie_maxlife)
1773 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1774
Emeric Brun647caf12009-06-30 17:57:00 +02001775 if (defproxy.rdp_cookie_name)
1776 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1777 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1778
Willy Tarreau01732802007-11-01 22:48:15 +01001779 if (defproxy.url_param_name)
1780 curproxy->url_param_name = strdup(defproxy.url_param_name);
1781 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001782
Benoitaffb4812009-03-25 13:02:10 +01001783 if (defproxy.hh_name)
1784 curproxy->hh_name = strdup(defproxy.hh_name);
1785 curproxy->hh_len = defproxy.hh_len;
1786 curproxy->hh_match_domain = defproxy.hh_match_domain;
1787
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001788 if (defproxy.iface_name)
1789 curproxy->iface_name = strdup(defproxy.iface_name);
1790 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001793 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001794 if (defproxy.capture_name)
1795 curproxy->capture_name = strdup(defproxy.capture_name);
1796 curproxy->capture_namelen = defproxy.capture_namelen;
1797 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799
Willy Tarreau977b8e42006-12-29 14:19:17 +01001800 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001801 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001802 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001803 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001804 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 curproxy->uri_auth = defproxy.uri_auth;
1806 curproxy->mon_net = defproxy.mon_net;
1807 curproxy->mon_mask = defproxy.mon_mask;
1808 if (defproxy.monitor_uri)
1809 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1810 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001811 if (defproxy.defbe.name)
1812 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001813
1814 /* get either a pointer to the logformat string or a copy of it */
1815 curproxy->logformat_string = defproxy.logformat_string;
1816 if (curproxy->logformat_string &&
1817 curproxy->logformat_string != default_http_log_format &&
1818 curproxy->logformat_string != default_tcp_log_format &&
1819 curproxy->logformat_string != clf_http_log_format)
1820 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821 }
1822
1823 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001824 curproxy->timeout.connect = defproxy.timeout.connect;
1825 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001826 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001827 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001828 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001829 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001830 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001831 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001832 curproxy->source_addr = defproxy.source_addr;
1833 }
1834
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001836
1837 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001838 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001839 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001840 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001841 LIST_INIT(&node->list);
1842 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1843 }
1844
Willy Tarreau196729e2012-05-31 19:30:26 +02001845 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1846 if (curproxy->uniqueid_format_string)
1847 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001848
1849 /* copy default header unique id */
1850 if (defproxy.header_unique_id)
1851 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1852
William Lallemand82fe75c2012-10-23 10:25:10 +02001853 /* default compression options */
1854 if (defproxy.comp != NULL) {
1855 curproxy->comp = calloc(1, sizeof(struct comp));
1856 curproxy->comp->algos = defproxy.comp->algos;
1857 curproxy->comp->types = defproxy.comp->types;
1858 }
1859
Willy Tarreaubaaee002006-06-26 02:48:02 +02001860 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001861 curproxy->conf.used_listener_id = EB_ROOT;
1862 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001863
Willy Tarreau93893792009-07-23 13:19:11 +02001864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 }
1866 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1867 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001868 /* FIXME-20070101: we should do this too at the end of the
1869 * config parsing to free all default values.
1870 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001871 free(defproxy.check_req);
1872 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001873 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001874 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001875 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001876 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001877 free(defproxy.capture_name);
1878 free(defproxy.monitor_uri);
1879 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001880 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001881 free(defproxy.fwdfor_hdr_name);
1882 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001883 free(defproxy.orgto_hdr_name);
1884 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001885 free(defproxy.server_id_hdr_name);
1886 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001887 free(defproxy.expect_str);
1888 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001889
Willy Tarreau39b06652012-06-01 10:58:06 +02001890 if (defproxy.logformat_string != default_http_log_format &&
1891 defproxy.logformat_string != default_tcp_log_format &&
1892 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001893 free(defproxy.logformat_string);
1894
1895 free(defproxy.uniqueid_format_string);
1896
Willy Tarreaua534fea2008-08-03 12:19:50 +02001897 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001898 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 /* we cannot free uri_auth because it might already be used */
1901 init_default_instance();
1902 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
1906 else if (curproxy == NULL) {
1907 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 }
1911
Willy Tarreau977b8e42006-12-29 14:19:17 +01001912
1913 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001915 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001916 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001917 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001918
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 if (curproxy == &defproxy) {
1920 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926
Emeric Bruned760922010-10-22 17:59:25 +02001927 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001928 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001933
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001934 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001935 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001936
1937 /* NOTE: the following line might create several listeners if there
1938 * are comma-separated IPs or port ranges. So all further processing
1939 * will have to be applied to all listeners created after last_listen.
1940 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001941 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1942 if (err_msg && *err_msg) {
1943 indent_msg(&err_msg, 2);
1944 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1945 }
1946 else
1947 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1948 file, linenum, args[0], args[1]);
1949 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
1952 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001953
Willy Tarreau4348fad2012-09-20 16:48:07 +02001954 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1955 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001956 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001957 }
1958
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001959 cur_arg = 2;
1960 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001961 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001962 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001963 char *err;
1964
Willy Tarreau26982662012-09-12 23:17:10 +02001965 kw = bind_find_kw(args[cur_arg]);
1966 if (kw) {
1967 char *err = NULL;
1968 int code;
1969
1970 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001971 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1972 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001973 cur_arg += 1 + kw->skip ;
1974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
1976 }
1977
Willy Tarreau4348fad2012-09-20 16:48:07 +02001978 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001979 err_code |= code;
1980
1981 if (code) {
1982 if (err && *err) {
1983 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001984 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001985 }
1986 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001987 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1988 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001989 if (code & ERR_FATAL) {
1990 free(err);
1991 cur_arg += 1 + kw->skip;
1992 goto out;
1993 }
1994 }
1995 free(err);
1996 cur_arg += 1 + kw->skip;
1997 continue;
1998 }
1999
Willy Tarreau8638f482012-09-18 18:01:17 +02002000 err = NULL;
2001 if (!bind_dumped) {
2002 bind_dump_kws(&err);
2003 indent_msg(&err, 4);
2004 bind_dumped = 1;
2005 }
2006
2007 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2008 file, linenum, args[0], args[1], args[cur_arg],
2009 err ? " Registered keywords :" : "", err ? err : "");
2010 free(err);
2011
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002014 }
Willy Tarreau93893792009-07-23 13:19:11 +02002015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 }
2017 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2018 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2019 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2020 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002021 err_code |= ERR_ALERT | ERR_FATAL;
2022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002024 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 /* flush useless bits */
2028 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002031 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002032 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002034
Willy Tarreau1c47f852006-07-09 08:22:27 +02002035 if (!*args[1]) {
2036 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_ALERT | ERR_FATAL;
2039 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002040 }
2041
Willy Tarreaua534fea2008-08-03 12:19:50 +02002042 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002043 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002044 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002045 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002046 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2047
Willy Tarreau93893792009-07-23 13:19:11 +02002048 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2051 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2052 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2053 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2054 else {
2055 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058 }
2059 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002060 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002061 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002062
2063 if (curproxy == &defproxy) {
2064 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2065 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002068 }
2069
2070 if (!*args[1]) {
2071 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002075 }
2076
2077 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002078 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002079
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002080 if (curproxy->uuid <= 0) {
2081 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002082 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002085 }
2086
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002087 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2088 if (node) {
2089 struct proxy *target = container_of(node, struct proxy, conf.id);
2090 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2091 file, linenum, proxy_type_str(curproxy), curproxy->id,
2092 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
2095 }
2096 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002097 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002098 else if (!strcmp(args[0], "description")) {
2099 int i, len=0;
2100 char *d;
2101
Cyril Bonté99ed3272010-01-24 23:29:44 +01002102 if (curproxy == &defproxy) {
2103 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2104 file, linenum, args[0]);
2105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
2108
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002109 if (!*args[1]) {
2110 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2111 file, linenum, args[0]);
2112 return -1;
2113 }
2114
2115 for(i=1; *args[i]; i++)
2116 len += strlen(args[i])+1;
2117
2118 d = (char *)calloc(1, len);
2119 curproxy->desc = d;
2120
2121 d += sprintf(d, "%s", args[1]);
2122 for(i=2; *args[i]; i++)
2123 d += sprintf(d, " %s", args[i]);
2124
2125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2127 curproxy->state = PR_STSTOPPED;
2128 }
2129 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2130 curproxy->state = PR_STNEW;
2131 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002132 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2133 int cur_arg = 1;
2134 unsigned int set = 0;
2135
2136 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002137 unsigned int low, high;
2138
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002139 if (strcmp(args[cur_arg], "all") == 0) {
2140 set = 0;
2141 break;
2142 }
2143 else if (strcmp(args[cur_arg], "odd") == 0) {
2144 set |= 0x55555555;
2145 }
2146 else if (strcmp(args[cur_arg], "even") == 0) {
2147 set |= 0xAAAAAAAA;
2148 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002149 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002150 char *dash = strchr(args[cur_arg], '-');
2151
2152 low = high = str2uic(args[cur_arg]);
2153 if (dash)
2154 high = str2uic(dash + 1);
2155
2156 if (high < low) {
2157 unsigned int swap = low;
2158 low = high;
2159 high = swap;
2160 }
2161
2162 if (low < 1 || high > 32) {
2163 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002164 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002167 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002168
2169 if (high > global.nbproc) {
2170 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2171 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002173 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002174 while (low <= high)
2175 set |= 1 << (low++ - 1);
2176 }
2177 else {
2178 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2179 file, linenum, args[0]);
2180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002182 }
2183 cur_arg++;
2184 }
2185 curproxy->bind_proc = set;
2186 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002187 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002188 if (curproxy == &defproxy) {
2189 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002192 }
2193
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002194 err = invalid_char(args[1]);
2195 if (err) {
2196 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2197 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002199 }
2200
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002201 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2202 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2203 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002206 }
2207 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2209 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210
Willy Tarreau977b8e42006-12-29 14:19:17 +01002211 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002213
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 if (*(args[1]) == 0) {
2215 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2216 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002220
Willy Tarreau67402132012-05-31 20:40:20 +02002221 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002222 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002223 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002224 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 curproxy->cookie_name = strdup(args[1]);
2226 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 cur_arg = 2;
2229 while (*(args[cur_arg])) {
2230 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002231 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
2233 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002234 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 }
2236 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002237 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }
2239 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002240 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002245 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002246 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002249 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002251 else if (!strcmp(args[cur_arg], "httponly")) {
2252 curproxy->ck_opts |= PR_CK_HTTPONLY;
2253 }
2254 else if (!strcmp(args[cur_arg], "secure")) {
2255 curproxy->ck_opts |= PR_CK_SECURE;
2256 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002257 else if (!strcmp(args[cur_arg], "domain")) {
2258 if (!*args[cur_arg + 1]) {
2259 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2260 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002263 }
2264
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002265 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002266 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002267 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2268 " dots nor does not start with a dot."
2269 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002270 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002271 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002272 }
2273
2274 err = invalid_domainchar(args[cur_arg + 1]);
2275 if (err) {
2276 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2277 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002280 }
2281
Willy Tarreau68a897b2009-12-03 23:28:34 +01002282 if (!curproxy->cookie_domain) {
2283 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2284 } else {
2285 /* one domain was already specified, add another one by
2286 * building the string which will be returned along with
2287 * the cookie.
2288 */
2289 char *new_ptr;
2290 int new_len = strlen(curproxy->cookie_domain) +
2291 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2292 new_ptr = malloc(new_len);
2293 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2294 free(curproxy->cookie_domain);
2295 curproxy->cookie_domain = new_ptr;
2296 }
Willy Tarreau31936852010-10-06 16:59:56 +02002297 cur_arg++;
2298 }
2299 else if (!strcmp(args[cur_arg], "maxidle")) {
2300 unsigned int maxidle;
2301 const char *res;
2302
2303 if (!*args[cur_arg + 1]) {
2304 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2305 file, linenum, args[cur_arg]);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2311 if (res) {
2312 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2313 file, linenum, *res, args[cur_arg]);
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
2317 curproxy->cookie_maxidle = maxidle;
2318 cur_arg++;
2319 }
2320 else if (!strcmp(args[cur_arg], "maxlife")) {
2321 unsigned int maxlife;
2322 const char *res;
2323
2324 if (!*args[cur_arg + 1]) {
2325 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2326 file, linenum, args[cur_arg]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330
2331 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2332 if (res) {
2333 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2334 file, linenum, *res, args[cur_arg]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002339 cur_arg++;
2340 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002342 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 +02002343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
2347 cur_arg++;
2348 }
Willy Tarreau67402132012-05-31 20:40:20 +02002349 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354
Willy Tarreau67402132012-05-31 20:40:20 +02002355 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2357 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002360
Willy Tarreau67402132012-05-31 20:40:20 +02002361 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002362 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2363 file, linenum);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002367 else if (!strcmp(args[0], "persist")) { /* persist */
2368 if (*(args[1]) == 0) {
2369 Alert("parsing [%s:%d] : missing persist method.\n",
2370 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002373 }
2374
2375 if (!strncmp(args[1], "rdp-cookie", 10)) {
2376 curproxy->options2 |= PR_O2_RDPC_PRST;
2377
Emeric Brunb982a3d2010-01-04 15:45:53 +01002378 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002379 const char *beg, *end;
2380
2381 beg = args[1] + 11;
2382 end = strchr(beg, ')');
2383
2384 if (!end || end == beg) {
2385 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002389 }
2390
2391 free(curproxy->rdp_cookie_name);
2392 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2393 curproxy->rdp_cookie_len = end-beg;
2394 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002395 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002396 free(curproxy->rdp_cookie_name);
2397 curproxy->rdp_cookie_name = strdup("msts");
2398 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2399 }
2400 else { /* syntax */
2401 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2402 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002405 }
2406 }
2407 else {
2408 Alert("parsing [%s:%d] : unknown persist method.\n",
2409 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002412 }
2413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002415 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
2422
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002427 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002433 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002434 curproxy->appsession_name = strdup(args[1]);
2435 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2436 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002437 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2438 if (err) {
2439 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2440 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002443 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002444 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002445
Willy Tarreau51041c72007-09-09 21:56:53 +02002446 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2447 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_ABORT;
2449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002451
2452 cur_arg = 6;
2453 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002454 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2455 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002456 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002457 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002458 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002459 } else if (!strcmp(args[cur_arg], "prefix")) {
2460 curproxy->options2 |= PR_O2_AS_PFX;
2461 } else if (!strcmp(args[cur_arg], "mode")) {
2462 if (!*args[cur_arg + 1]) {
2463 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2464 file, linenum, args[0], args[cur_arg]);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468
2469 cur_arg++;
2470 if (!strcmp(args[cur_arg], "query-string")) {
2471 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2472 curproxy->options2 |= PR_O2_AS_M_QS;
2473 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2474 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2475 curproxy->options2 |= PR_O2_AS_M_PP;
2476 } else {
2477 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002482 cur_arg++;
2483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 } /* Url App Session */
2485 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002486 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002490 if (curproxy == &defproxy) {
2491 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 if (*(args[4]) == 0) {
2497 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002502 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 curproxy->capture_name = strdup(args[2]);
2504 curproxy->capture_namelen = strlen(curproxy->capture_name);
2505 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 curproxy->to_log |= LW_COOKIE;
2507 }
2508 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2509 struct cap_hdr *hdr;
2510
2511 if (curproxy == &defproxy) {
2512 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 +02002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 }
2516
2517 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2518 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2519 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523
2524 hdr = calloc(sizeof(struct cap_hdr), 1);
2525 hdr->next = curproxy->req_cap;
2526 hdr->name = strdup(args[3]);
2527 hdr->namelen = strlen(args[3]);
2528 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002529 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 hdr->index = curproxy->nb_req_cap++;
2531 curproxy->req_cap = hdr;
2532 curproxy->to_log |= LW_REQHDR;
2533 }
2534 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2535 struct cap_hdr *hdr;
2536
2537 if (curproxy == &defproxy) {
2538 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 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 }
2542
2543 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2544 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2545 file, linenum, args[0], args[1]);
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 }
2549 hdr = calloc(sizeof(struct cap_hdr), 1);
2550 hdr->next = curproxy->rsp_cap;
2551 hdr->name = strdup(args[3]);
2552 hdr->namelen = strlen(args[3]);
2553 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002554 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 hdr->index = curproxy->nb_rsp_cap++;
2556 curproxy->rsp_cap = hdr;
2557 curproxy->to_log |= LW_RSPHDR;
2558 }
2559 else {
2560 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2561 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002567 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 if (*(args[1]) == 0) {
2571 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2572 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576 curproxy->conn_retries = atol(args[1]);
2577 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002578 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002579 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002580
2581 if (curproxy == &defproxy) {
2582 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586
Willy Tarreauff011f22011-01-06 17:51:27 +01002587 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002588 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2589 file, linenum, args[0]);
2590 err_code |= ERR_WARN;
2591 }
2592
Willy Tarreauff011f22011-01-06 17:51:27 +01002593 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002594
Willy Tarreauff011f22011-01-06 17:51:27 +01002595 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002596 err_code |= ERR_ALERT | ERR_ABORT;
2597 goto out;
2598 }
2599
Willy Tarreauff011f22011-01-06 17:51:27 +01002600 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2601 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002602 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002603 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2604 /* set the header name and length into the proxy structure */
2605 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2606 err_code |= ERR_WARN;
2607
2608 if (!*args[1]) {
2609 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2610 file, linenum, args[0]);
2611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
2613 }
2614
2615 /* set the desired header name */
2616 free(curproxy->server_id_hdr_name);
2617 curproxy->server_id_hdr_name = strdup(args[1]);
2618 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2619 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002620 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002621 if (curproxy == &defproxy) {
2622 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002625 }
2626
Willy Tarreauef6494c2010-01-28 17:12:36 +01002627 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002628 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002632 }
2633
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002634 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2635 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2636 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002639 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002640
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002641 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002642 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002643 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002644 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 struct redirect_rule *rule;
2646 int cur_arg;
2647 int type = REDIRECT_TYPE_NONE;
2648 int code = 302;
2649 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002650 char *cookie = NULL;
2651 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002652 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002653
Cyril Bonté99ed3272010-01-24 23:29:44 +01002654 if (curproxy == &defproxy) {
2655 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
2658 }
2659
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660 cur_arg = 1;
2661 while (*(args[cur_arg])) {
2662 if (!strcmp(args[cur_arg], "location")) {
2663 if (!*args[cur_arg + 1]) {
2664 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2665 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002668 }
2669
2670 type = REDIRECT_TYPE_LOCATION;
2671 cur_arg++;
2672 destination = args[cur_arg];
2673 }
2674 else if (!strcmp(args[cur_arg], "prefix")) {
2675 if (!*args[cur_arg + 1]) {
2676 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2677 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680 }
2681
2682 type = REDIRECT_TYPE_PREFIX;
2683 cur_arg++;
2684 destination = args[cur_arg];
2685 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002686 else if (!strcmp(args[cur_arg], "scheme")) {
2687 if (!*args[cur_arg + 1]) {
2688 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2689 file, linenum, args[0], args[cur_arg]);
2690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693
2694 type = REDIRECT_TYPE_SCHEME;
2695 cur_arg++;
2696 destination = args[cur_arg];
2697 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002698 else if (!strcmp(args[cur_arg], "set-cookie")) {
2699 if (!*args[cur_arg + 1]) {
2700 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2701 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002704 }
2705
2706 cur_arg++;
2707 cookie = args[cur_arg];
2708 cookie_set = 1;
2709 }
2710 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2711 if (!*args[cur_arg + 1]) {
2712 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2713 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002716 }
2717
2718 cur_arg++;
2719 cookie = args[cur_arg];
2720 cookie_set = 0;
2721 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002722 else if (!strcmp(args[cur_arg],"code")) {
2723 if (!*args[cur_arg + 1]) {
2724 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2725 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002728 }
2729 cur_arg++;
2730 code = atol(args[cur_arg]);
2731 if (code < 301 || code > 303) {
2732 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2733 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002736 }
2737 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002738 else if (!strcmp(args[cur_arg],"drop-query")) {
2739 flags |= REDIRECT_FLAG_DROP_QS;
2740 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002741 else if (!strcmp(args[cur_arg],"append-slash")) {
2742 flags |= REDIRECT_FLAG_APPEND_SLASH;
2743 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002744 else if (strcmp(args[cur_arg], "if") == 0 ||
2745 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002746 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002747 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002748 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2749 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
2752 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002753 break;
2754 }
2755 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002756 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002757 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002760 }
2761 cur_arg++;
2762 }
2763
2764 if (type == REDIRECT_TYPE_NONE) {
2765 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2766 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002769 }
2770
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002771 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2772 rule->cond = cond;
2773 rule->rdr_str = strdup(destination);
2774 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002775 if (cookie) {
2776 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002777 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002778 */
2779 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002780 if (cookie_set) {
2781 rule->cookie_str = malloc(rule->cookie_len + 10);
2782 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2783 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2784 rule->cookie_len += 9;
2785 } else {
2786 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002787 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002788 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2789 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002790 }
2791 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002792 rule->type = type;
2793 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002794 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002795 LIST_INIT(&rule->list);
2796 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002797 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2798 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002799 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002800 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002801 struct switching_rule *rule;
2802
Willy Tarreaub099aca2008-10-12 17:26:37 +02002803 if (curproxy == &defproxy) {
2804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002807 }
2808
Willy Tarreau55ea7572007-06-17 19:56:27 +02002809 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002811
2812 if (*(args[1]) == 0) {
2813 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002816 }
2817
Willy Tarreauef6494c2010-01-28 17:12:36 +01002818 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002819 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2820 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002823 }
2824
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002825 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2826 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2827 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002830 }
2831
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002832 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002833
Willy Tarreau55ea7572007-06-17 19:56:27 +02002834 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2835 rule->cond = cond;
2836 rule->be.name = strdup(args[1]);
2837 LIST_INIT(&rule->list);
2838 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2839 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002840 else if (strcmp(args[0], "use-server") == 0) {
2841 struct server_rule *rule;
2842
2843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
2849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2850 err_code |= ERR_WARN;
2851
2852 if (*(args[1]) == 0) {
2853 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857
2858 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2859 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2860 file, linenum, args[0]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002865 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2866 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2867 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
2871
2872 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2873
2874 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2875 rule->cond = cond;
2876 rule->srv.name = strdup(args[1]);
2877 LIST_INIT(&rule->list);
2878 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2879 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2880 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002881 else if ((!strcmp(args[0], "force-persist")) ||
2882 (!strcmp(args[0], "ignore-persist"))) {
2883 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002884
2885 if (curproxy == &defproxy) {
2886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
2891 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2892 err_code |= ERR_WARN;
2893
Willy Tarreauef6494c2010-01-28 17:12:36 +01002894 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002895 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2896 file, linenum, args[0]);
2897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
2899 }
2900
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002901 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2902 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2903 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002908 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002909
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002910 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002911 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002912 if (!strcmp(args[0], "force-persist")) {
2913 rule->type = PERSIST_TYPE_FORCE;
2914 } else {
2915 rule->type = PERSIST_TYPE_IGNORE;
2916 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002917 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002918 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002919 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002920 else if (!strcmp(args[0], "stick-table")) {
2921 int myidx = 1;
2922
Emeric Brun32da3c42010-09-23 18:39:19 +02002923 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002924 curproxy->table.type = (unsigned int)-1;
2925 while (*args[myidx]) {
2926 const char *err;
2927
2928 if (strcmp(args[myidx], "size") == 0) {
2929 myidx++;
2930 if (!*(args[myidx])) {
2931 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2932 file, linenum, args[myidx-1]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2937 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2938 file, linenum, *err, args[myidx-1]);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002942 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002944 else if (strcmp(args[myidx], "peers") == 0) {
2945 myidx++;
2946 if (!*(args[myidx])) {
2947 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2948 file, linenum, args[myidx-1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 curproxy->table.peers.name = strdup(args[myidx++]);
2953 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 else if (strcmp(args[myidx], "expire") == 0) {
2955 myidx++;
2956 if (!*(args[myidx])) {
2957 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2958 file, linenum, args[myidx-1]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2963 if (err) {
2964 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2965 file, linenum, *err, args[myidx-1]);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
2969 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002970 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 }
2972 else if (strcmp(args[myidx], "nopurge") == 0) {
2973 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002974 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002975 }
2976 else if (strcmp(args[myidx], "type") == 0) {
2977 myidx++;
2978 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2979 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2980 file, linenum, args[myidx]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002984 /* myidx already points to next arg */
2985 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002986 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002987 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002988 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002989
2990 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002991 nw = args[myidx];
2992 while (*nw) {
2993 /* the "store" keyword supports a comma-separated list */
2994 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002995 sa = NULL; /* store arg */
2996 while (*nw && *nw != ',') {
2997 if (*nw == '(') {
2998 *nw = 0;
2999 sa = ++nw;
3000 while (*nw != ')') {
3001 if (!*nw) {
3002 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3003 file, linenum, args[0], cw);
3004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007 nw++;
3008 }
3009 *nw = '\0';
3010 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003011 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003012 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003013 if (*nw)
3014 *nw++ = '\0';
3015 type = stktable_get_data_type(cw);
3016 if (type < 0) {
3017 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3018 file, linenum, args[0], cw);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
Willy Tarreauac782882010-06-20 10:41:54 +02003022
3023 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3024 switch (err) {
3025 case PE_NONE: break;
3026 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003027 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3028 file, linenum, args[0], cw);
3029 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003030 break;
3031
3032 case PE_ARG_MISSING:
3033 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3034 file, linenum, args[0], cw);
3035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037
3038 case PE_ARG_NOT_USED:
3039 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3040 file, linenum, args[0], cw);
3041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
3043
3044 default:
3045 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3046 file, linenum, args[0], cw);
3047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003049 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003050 }
3051 myidx++;
3052 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003053 else {
3054 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3055 file, linenum, args[myidx]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
3060
3061 if (!curproxy->table.size) {
3062 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3063 file, linenum);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067
3068 if (curproxy->table.type == (unsigned int)-1) {
3069 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3070 file, linenum);
3071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074 }
3075 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003076 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003077 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003078 int myidx = 0;
3079 const char *name = NULL;
3080 int flags;
3081
3082 if (curproxy == &defproxy) {
3083 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
3086 }
3087
3088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3089 err_code |= ERR_WARN;
3090 goto out;
3091 }
3092
3093 myidx++;
3094 if ((strcmp(args[myidx], "store") == 0) ||
3095 (strcmp(args[myidx], "store-request") == 0)) {
3096 myidx++;
3097 flags = STK_IS_STORE;
3098 }
3099 else if (strcmp(args[myidx], "store-response") == 0) {
3100 myidx++;
3101 flags = STK_IS_STORE | STK_ON_RSP;
3102 }
3103 else if (strcmp(args[myidx], "match") == 0) {
3104 myidx++;
3105 flags = STK_IS_MATCH;
3106 }
3107 else if (strcmp(args[myidx], "on") == 0) {
3108 myidx++;
3109 flags = STK_IS_MATCH | STK_IS_STORE;
3110 }
3111 else {
3112 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 if (*(args[myidx]) == 0) {
3118 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121 }
3122
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003123 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003125 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129
3130 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003131 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003132 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3133 file, linenum, args[0], expr->fetch->kw);
3134 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003135 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003136 goto out;
3137 }
3138 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003139 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003140 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3141 file, linenum, args[0], expr->fetch->kw);
3142 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003143 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003144 goto out;
3145 }
3146 }
3147
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003148 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3149 if (expr->fetch->cap & SMP_CAP_L7)
3150 curproxy->acl_requires |= ACL_USE_L7_ANY;
3151
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 if (strcmp(args[myidx], "table") == 0) {
3153 myidx++;
3154 name = args[myidx++];
3155 }
3156
Willy Tarreauef6494c2010-01-28 17:12:36 +01003157 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003158 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3159 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3160 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003161 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003162 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003163 goto out;
3164 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003165 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003166 else if (*(args[myidx])) {
3167 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3168 file, linenum, args[0], args[myidx]);
3169 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003170 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003171 goto out;
3172 }
Emeric Brun97679e72010-09-23 17:56:44 +02003173 if (flags & STK_ON_RSP)
3174 err_code |= warnif_cond_requires_req(cond, file, linenum);
3175 else
3176 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003177
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3179 rule->cond = cond;
3180 rule->expr = expr;
3181 rule->flags = flags;
3182 rule->table.name = name ? strdup(name) : NULL;
3183 LIST_INIT(&rule->list);
3184 if (flags & STK_ON_RSP)
3185 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3186 else
3187 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003190 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003192
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3194 curproxy->uri_auth = NULL; /* we must detach from the default config */
3195
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003196 if (!*args[1]) {
3197 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003198 } else if (!strcmp(args[1], "admin")) {
3199 struct stats_admin_rule *rule;
3200
3201 if (curproxy == &defproxy) {
3202 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3208 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
3211 }
3212
3213 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3214 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3215 file, linenum, args[0], args[1]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003219 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3220 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3221 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225
3226 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3227
3228 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3229 rule->cond = cond;
3230 LIST_INIT(&rule->list);
3231 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 } else if (!strcmp(args[1], "uri")) {
3233 if (*(args[2]) == 0) {
3234 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 }
3242 } else if (!strcmp(args[1], "realm")) {
3243 if (*(args[2]) == 0) {
3244 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003249 err_code |= ERR_ALERT | ERR_ABORT;
3250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003252 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003253 unsigned interval;
3254
3255 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3256 if (err) {
3257 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3258 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003261 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3262 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_ABORT;
3264 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003265 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003266 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003267 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003268
3269 if (curproxy == &defproxy) {
3270 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
3273 }
3274
3275 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3276 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3277 err_code |= ERR_ALERT | ERR_ABORT;
3278 goto out;
3279 }
3280
Willy Tarreauff011f22011-01-06 17:51:27 +01003281 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3282 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003283 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3284 file, linenum, args[0]);
3285 err_code |= ERR_WARN;
3286 }
3287
Willy Tarreauff011f22011-01-06 17:51:27 +01003288 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003289
Willy Tarreauff011f22011-01-06 17:51:27 +01003290 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003291 err_code |= ERR_ALERT | ERR_ABORT;
3292 goto out;
3293 }
3294
Willy Tarreauff011f22011-01-06 17:51:27 +01003295 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3296 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003297
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 } else if (!strcmp(args[1], "auth")) {
3299 if (*(args[2]) == 0) {
3300 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3304 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_ABORT;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
3308 } else if (!strcmp(args[1], "scope")) {
3309 if (*(args[2]) == 0) {
3310 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3314 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_ABORT;
3316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 }
3318 } else if (!strcmp(args[1], "enable")) {
3319 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3320 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_ABORT;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003324 } else if (!strcmp(args[1], "hide-version")) {
3325 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_ALERT | ERR_ABORT;
3328 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003329 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003330 } else if (!strcmp(args[1], "show-legends")) {
3331 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3332 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3333 err_code |= ERR_ALERT | ERR_ABORT;
3334 goto out;
3335 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003336 } else if (!strcmp(args[1], "show-node")) {
3337
3338 if (*args[2]) {
3339 int i;
3340 char c;
3341
3342 for (i=0; args[2][i]; i++) {
3343 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003344 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3345 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003346 break;
3347 }
3348
3349 if (!i || args[2][i]) {
3350 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3351 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3352 file, linenum, args[0], args[1]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356 }
3357
3358 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3359 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3360 err_code |= ERR_ALERT | ERR_ABORT;
3361 goto out;
3362 }
3363 } else if (!strcmp(args[1], "show-desc")) {
3364 char *desc = NULL;
3365
3366 if (*args[2]) {
3367 int i, len=0;
3368 char *d;
3369
3370 for(i=2; *args[i]; i++)
3371 len += strlen(args[i])+1;
3372
3373 desc = d = (char *)calloc(1, len);
3374
3375 d += sprintf(d, "%s", args[2]);
3376 for(i=3; *args[i]; i++)
3377 d += sprintf(d, " %s", args[i]);
3378 }
3379
3380 if (!*args[2] && !global.desc)
3381 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3382 file, linenum, args[1]);
3383 else {
3384 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3385 free(desc);
3386 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3387 err_code |= ERR_ALERT | ERR_ABORT;
3388 goto out;
3389 }
3390 free(desc);
3391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003393stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003394 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 +01003395 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 }
3399 }
3400 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003401 int optnum;
3402
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003403 if (*(args[1]) == '\0') {
3404 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3405 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003409
3410 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3411 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003412 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3413 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3414 file, linenum, cfg_opts[optnum].name);
3415 err_code |= ERR_ALERT | ERR_FATAL;
3416 goto out;
3417 }
Willy Tarreau93893792009-07-23 13:19:11 +02003418 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3419 err_code |= ERR_WARN;
3420 goto out;
3421 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003422
Willy Tarreau3842f002009-06-14 11:39:52 +02003423 curproxy->no_options &= ~cfg_opts[optnum].val;
3424 curproxy->options &= ~cfg_opts[optnum].val;
3425
3426 switch (kwm) {
3427 case KWM_STD:
3428 curproxy->options |= cfg_opts[optnum].val;
3429 break;
3430 case KWM_NO:
3431 curproxy->no_options |= cfg_opts[optnum].val;
3432 break;
3433 case KWM_DEF: /* already cleared */
3434 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003435 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003436
Willy Tarreau93893792009-07-23 13:19:11 +02003437 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003438 }
3439 }
3440
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003441 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3442 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003443 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3444 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3445 file, linenum, cfg_opts2[optnum].name);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
Willy Tarreau93893792009-07-23 13:19:11 +02003449 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3450 err_code |= ERR_WARN;
3451 goto out;
3452 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003453
Willy Tarreau3842f002009-06-14 11:39:52 +02003454 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3455 curproxy->options2 &= ~cfg_opts2[optnum].val;
3456
3457 switch (kwm) {
3458 case KWM_STD:
3459 curproxy->options2 |= cfg_opts2[optnum].val;
3460 break;
3461 case KWM_NO:
3462 curproxy->no_options2 |= cfg_opts2[optnum].val;
3463 break;
3464 case KWM_DEF: /* already cleared */
3465 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003466 }
Willy Tarreau93893792009-07-23 13:19:11 +02003467 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003468 }
3469 }
3470
Willy Tarreau3842f002009-06-14 11:39:52 +02003471 if (kwm != KWM_STD) {
3472 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003473 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003476 }
3477
Emeric Brun3a058f32009-06-30 18:26:00 +02003478 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003479 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003481 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003482 if (*(args[2]) != '\0') {
3483 if (!strcmp(args[2], "clf")) {
3484 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003485 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003486 } else {
3487 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003490 }
3491 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003492 if (curproxy->logformat_string != default_http_log_format &&
3493 curproxy->logformat_string != default_tcp_log_format &&
3494 curproxy->logformat_string != clf_http_log_format)
3495 free(curproxy->logformat_string);
3496 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003497 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003498 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003500 if (curproxy->logformat_string != default_http_log_format &&
3501 curproxy->logformat_string != default_tcp_log_format &&
3502 curproxy->logformat_string != clf_http_log_format)
3503 free(curproxy->logformat_string);
3504 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 else if (!strcmp(args[1], "tcpka")) {
3507 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003508 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003510
3511 if (curproxy->cap & PR_CAP_FE)
3512 curproxy->options |= PR_O_TCP_CLI_KA;
3513 if (curproxy->cap & PR_CAP_BE)
3514 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003515 }
3516 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003517 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_WARN;
3519
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003521 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003522 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003523 curproxy->options2 &= ~PR_O2_CHK_ANY;
3524 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 if (!*args[2]) { /* no argument */
3526 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3527 curproxy->check_len = strlen(DEF_CHECK_REQ);
3528 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003529 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 curproxy->check_req = (char *)malloc(reqlen);
3531 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003532 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003534 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 if (*args[4])
3536 reqlen += strlen(args[4]);
3537 else
3538 reqlen += strlen("HTTP/1.0");
3539
3540 curproxy->check_req = (char *)malloc(reqlen);
3541 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003542 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003544 }
3545 else if (!strcmp(args[1], "ssl-hello-chk")) {
3546 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003547 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003549
Willy Tarreaua534fea2008-08-03 12:19:50 +02003550 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003551 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003552 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003553 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 }
Willy Tarreau23677902007-05-08 23:50:35 +02003555 else if (!strcmp(args[1], "smtpchk")) {
3556 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003557 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003558 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003559 curproxy->options2 &= ~PR_O2_CHK_ANY;
3560 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003561
3562 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3563 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3564 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3565 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3566 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3567 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3568 curproxy->check_req = (char *)malloc(reqlen);
3569 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3570 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3571 } else {
3572 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3573 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3574 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3575 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3576 }
3577 }
3578 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003579 else if (!strcmp(args[1], "pgsql-check")) {
3580 /* use PostgreSQL request to check servers' health */
3581 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3582 err_code |= ERR_WARN;
3583
3584 free(curproxy->check_req);
3585 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003586 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003587 curproxy->options2 |= PR_O2_PGSQL_CHK;
3588
3589 if (*(args[2])) {
3590 int cur_arg = 2;
3591
3592 while (*(args[cur_arg])) {
3593 if (strcmp(args[cur_arg], "user") == 0) {
3594 char * packet;
3595 uint32_t packet_len;
3596 uint32_t pv;
3597
3598 /* suboption header - needs additional argument for it */
3599 if (*(args[cur_arg+1]) == 0) {
3600 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3601 file, linenum, args[0], args[1], args[cur_arg]);
3602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
3604 }
3605
3606 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3607 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3608 pv = htonl(0x30000); /* protocol version 3.0 */
3609
3610 packet = (char*) calloc(1, packet_len);
3611
3612 memcpy(packet + 4, &pv, 4);
3613
3614 /* copy "user" */
3615 memcpy(packet + 8, "user", 4);
3616
3617 /* copy username */
3618 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3619
3620 free(curproxy->check_req);
3621 curproxy->check_req = packet;
3622 curproxy->check_len = packet_len;
3623
3624 packet_len = htonl(packet_len);
3625 memcpy(packet, &packet_len, 4);
3626 cur_arg += 2;
3627 } else {
3628 /* unknown suboption - catchall */
3629 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3630 file, linenum, args[0], args[1]);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634 } /* end while loop */
3635 }
3636 }
3637
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003638 else if (!strcmp(args[1], "redis-check")) {
3639 /* use REDIS PING request to check servers' health */
3640 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3641 err_code |= ERR_WARN;
3642
3643 free(curproxy->check_req);
3644 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003645 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003646 curproxy->options2 |= PR_O2_REDIS_CHK;
3647
3648 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3649 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3650 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3651 }
3652
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003653 else if (!strcmp(args[1], "mysql-check")) {
3654 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003655 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3656 err_code |= ERR_WARN;
3657
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003658 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003659 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003660 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003661 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003662
3663 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3664 * const char mysql40_client_auth_pkt[] = {
3665 * "\x0e\x00\x00" // packet length
3666 * "\x01" // packet number
3667 * "\x00\x00" // client capabilities
3668 * "\x00\x00\x01" // max packet
3669 * "haproxy\x00" // username (null terminated string)
3670 * "\x00" // filler (always 0x00)
3671 * "\x01\x00\x00" // packet length
3672 * "\x00" // packet number
3673 * "\x01" // COM_QUIT command
3674 * };
3675 */
3676
3677 if (*(args[2])) {
3678 int cur_arg = 2;
3679
3680 while (*(args[cur_arg])) {
3681 if (strcmp(args[cur_arg], "user") == 0) {
3682 char *mysqluser;
3683 int packetlen, reqlen, userlen;
3684
3685 /* suboption header - needs additional argument for it */
3686 if (*(args[cur_arg+1]) == 0) {
3687 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3688 file, linenum, args[0], args[1], args[cur_arg]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692 mysqluser = args[cur_arg + 1];
3693 userlen = strlen(mysqluser);
3694 packetlen = userlen + 7;
3695 reqlen = packetlen + 9;
3696
3697 free(curproxy->check_req);
3698 curproxy->check_req = (char *)calloc(1, reqlen);
3699 curproxy->check_len = reqlen;
3700
3701 snprintf(curproxy->check_req, 4, "%c%c%c",
3702 ((unsigned char) packetlen & 0xff),
3703 ((unsigned char) (packetlen >> 8) & 0xff),
3704 ((unsigned char) (packetlen >> 16) & 0xff));
3705
3706 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003707 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003708 curproxy->check_req[8] = 1;
3709 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3710 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3711 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3712 cur_arg += 2;
3713 } else {
3714 /* unknown suboption - catchall */
3715 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3716 file, linenum, args[0], args[1]);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 } /* end while loop */
3721 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003722 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003723 else if (!strcmp(args[1], "ldap-check")) {
3724 /* use LDAP request to check servers' health */
3725 free(curproxy->check_req);
3726 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003727 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003728 curproxy->options2 |= PR_O2_LDAP_CHK;
3729
3730 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3731 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3732 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3733 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003734 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003735 int cur_arg;
3736
3737 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3738 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003739 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003740
Willy Tarreau87cf5142011-08-19 22:57:24 +02003741 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003742
3743 free(curproxy->fwdfor_hdr_name);
3744 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3745 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3746
3747 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3748 cur_arg = 2;
3749 while (*(args[cur_arg])) {
3750 if (!strcmp(args[cur_arg], "except")) {
3751 /* suboption except - needs additional argument for it */
3752 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3753 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3754 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003757 }
3758 /* flush useless bits */
3759 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003760 cur_arg += 2;
3761 } else if (!strcmp(args[cur_arg], "header")) {
3762 /* suboption header - needs additional argument for it */
3763 if (*(args[cur_arg+1]) == 0) {
3764 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3765 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003768 }
3769 free(curproxy->fwdfor_hdr_name);
3770 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3771 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3772 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003773 } else if (!strcmp(args[cur_arg], "if-none")) {
3774 curproxy->options &= ~PR_O_FF_ALWAYS;
3775 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003776 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003777 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003778 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003779 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003782 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003783 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003784 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003785 else if (!strcmp(args[1], "originalto")) {
3786 int cur_arg;
3787
3788 /* insert x-original-to field, but not for the IP address listed as an except.
3789 * set default options (ie: bitfield, header name, etc)
3790 */
3791
3792 curproxy->options |= PR_O_ORGTO;
3793
3794 free(curproxy->orgto_hdr_name);
3795 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3796 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3797
Willy Tarreau87cf5142011-08-19 22:57:24 +02003798 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003799 cur_arg = 2;
3800 while (*(args[cur_arg])) {
3801 if (!strcmp(args[cur_arg], "except")) {
3802 /* suboption except - needs additional argument for it */
3803 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3804 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3805 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003808 }
3809 /* flush useless bits */
3810 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3811 cur_arg += 2;
3812 } else if (!strcmp(args[cur_arg], "header")) {
3813 /* suboption header - needs additional argument for it */
3814 if (*(args[cur_arg+1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3816 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003819 }
3820 free(curproxy->orgto_hdr_name);
3821 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3822 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3823 cur_arg += 2;
3824 } else {
3825 /* unknown suboption - catchall */
3826 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3827 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003830 }
3831 } /* end while loop */
3832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 else {
3834 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
Willy Tarreau93893792009-07-23 13:19:11 +02003838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003840 else if (!strcmp(args[0], "default_backend")) {
3841 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003843
3844 if (*(args[1]) == 0) {
3845 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003848 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003849 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003850 curproxy->defbe.name = strdup(args[1]);
3851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003855
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003856 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3857 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 /* enable reconnections to dispatch */
3860 curproxy->options |= PR_O_REDISP;
3861 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003862 else if (!strcmp(args[0], "http-check")) {
3863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003865
3866 if (strcmp(args[1], "disable-on-404") == 0) {
3867 /* enable a graceful server shutdown on an HTTP 404 response */
3868 curproxy->options |= PR_O_DISABLE404;
3869 }
Willy Tarreauef781042010-01-27 11:53:01 +01003870 else if (strcmp(args[1], "send-state") == 0) {
3871 /* enable emission of the apparent state of a server in HTTP checks */
3872 curproxy->options2 |= PR_O2_CHK_SNDST;
3873 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003874 else if (strcmp(args[1], "expect") == 0) {
3875 const char *ptr_arg;
3876 int cur_arg;
3877
3878 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3879 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883
3884 cur_arg = 2;
3885 /* consider exclamation marks, sole or at the beginning of a word */
3886 while (*(ptr_arg = args[cur_arg])) {
3887 while (*ptr_arg == '!') {
3888 curproxy->options2 ^= PR_O2_EXP_INV;
3889 ptr_arg++;
3890 }
3891 if (*ptr_arg)
3892 break;
3893 cur_arg++;
3894 }
3895 /* now ptr_arg points to the beginning of a word past any possible
3896 * exclamation mark, and cur_arg is the argument which holds this word.
3897 */
3898 if (strcmp(ptr_arg, "status") == 0) {
3899 if (!*(args[cur_arg + 1])) {
3900 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3901 file, linenum, args[0], args[1], ptr_arg);
3902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
3904 }
3905 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003906 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003907 curproxy->expect_str = strdup(args[cur_arg + 1]);
3908 }
3909 else if (strcmp(ptr_arg, "string") == 0) {
3910 if (!*(args[cur_arg + 1])) {
3911 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3912 file, linenum, args[0], args[1], ptr_arg);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003917 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003918 curproxy->expect_str = strdup(args[cur_arg + 1]);
3919 }
3920 else if (strcmp(ptr_arg, "rstatus") == 0) {
3921 if (!*(args[cur_arg + 1])) {
3922 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3923 file, linenum, args[0], args[1], ptr_arg);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003928 free(curproxy->expect_str);
3929 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3930 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003931 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3932 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3933 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3934 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938 }
3939 else if (strcmp(ptr_arg, "rstring") == 0) {
3940 if (!*(args[cur_arg + 1])) {
3941 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3942 file, linenum, args[0], args[1], ptr_arg);
3943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
3945 }
3946 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003947 free(curproxy->expect_str);
3948 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3949 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003950 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3951 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3952 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3953 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957 }
3958 else {
3959 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3960 file, linenum, args[0], args[1], ptr_arg);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003965 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003966 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 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003969 }
3970 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003971 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003972 if (curproxy == &defproxy) {
3973 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003976 }
3977
Willy Tarreaub80c2302007-11-30 20:51:32 +01003978 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003980
3981 if (strcmp(args[1], "fail") == 0) {
3982 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003983 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003984 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3985 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003988 }
3989
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003990 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3991 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3992 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003995 }
3996 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3997 }
3998 else {
3999 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004002 }
4003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004#ifdef TPROXY
4005 else if (!strcmp(args[0], "transparent")) {
4006 /* enable transparent proxy connections */
4007 curproxy->options |= PR_O_TRANSP;
4008 }
4009#endif
4010 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004011 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004012 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004013
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014 if (*(args[1]) == 0) {
4015 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 }
4019 curproxy->maxconn = atol(args[1]);
4020 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004021 else if (!strcmp(args[0], "backlog")) { /* backlog */
4022 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004023 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004024
4025 if (*(args[1]) == 0) {
4026 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004029 }
4030 curproxy->backlog = atol(args[1]);
4031 }
Willy Tarreau86034312006-12-29 00:10:33 +01004032 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004033 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004035
Willy Tarreau86034312006-12-29 00:10:33 +01004036 if (*(args[1]) == 0) {
4037 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004040 }
4041 curproxy->fullconn = atol(args[1]);
4042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4044 if (*(args[1]) == 0) {
4045 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004049 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4050 if (err) {
4051 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4052 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004055 }
4056 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 }
4058 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004059 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 if (curproxy == &defproxy) {
4061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004065 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004067
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 if (strchr(args[1], ':') == NULL) {
4069 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004073 sk = str2sa(args[1]);
4074 if (!sk) {
4075 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004080 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 }
4082 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004083 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004085
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004086 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4087 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004091 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004092 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4093 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4094 err_code |= ERR_WARN;
4095
4096 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4097 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4098 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4099 }
4100 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4101 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4102 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4103 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004104 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4105 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4106 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4107 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004108 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004109 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 char *rport, *raddr;
4117 short realport = 0;
4118 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004120 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004124 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004125 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004126 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127
4128 if (!*args[2]) {
4129 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004134
4135 err = invalid_char(args[1]);
4136 if (err) {
4137 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4138 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004141 }
4142
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004143 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004144 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004145
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004146 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4147 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4148 err_code |= ERR_ALERT | ERR_ABORT;
4149 goto out;
4150 }
4151
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004152 /* the servers are linked backwards first */
4153 newsrv->next = curproxy->srv;
4154 curproxy->srv = newsrv;
4155 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004156 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004159 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004160 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004161 LIST_INIT(&newsrv->pendconns);
4162 do_check = 0;
4163 newsrv->state = SRV_RUNNING; /* early server setup */
4164 newsrv->last_change = now.tv_sec;
4165 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004167 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004168 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004169 * - IP: => port=+0, relative
4170 * - IP:N => port=N, absolute
4171 * - IP:+N => port=+N, relative
4172 * - IP:-N => port=-N, relative
4173 */
4174 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004175 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004176 if (rport) {
4177 *rport++ = 0;
4178 realport = atol(rport);
4179 if (!isdigit((unsigned char)*rport))
4180 newsrv->state |= SRV_MAPPORTS;
4181 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004183
Willy Tarreaufab5a432011-03-04 15:31:53 +01004184 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004185 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004186 if (!sk) {
4187 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004192 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4193 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004194
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004195 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004196 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4197 file, linenum, newsrv->addr.ss_family, args[2]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004201 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004203 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004204 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004205 newsrv->inter = curproxy->defsrv.inter;
4206 newsrv->fastinter = curproxy->defsrv.fastinter;
4207 newsrv->downinter = curproxy->defsrv.downinter;
4208 newsrv->rise = curproxy->defsrv.rise;
4209 newsrv->fall = curproxy->defsrv.fall;
4210 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4211 newsrv->minconn = curproxy->defsrv.minconn;
4212 newsrv->maxconn = curproxy->defsrv.maxconn;
4213 newsrv->slowstart = curproxy->defsrv.slowstart;
4214 newsrv->onerror = curproxy->defsrv.onerror;
4215 newsrv->consecutive_errors_limit
4216 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004217#ifdef OPENSSL
4218 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4219#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004220 newsrv->uweight = newsrv->iweight
4221 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004223 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 cur_arg = 3;
4226 } else {
4227 newsrv = &curproxy->defsrv;
4228 cur_arg = 1;
4229 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004230
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004232 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 newsrv->cookie = strdup(args[cur_arg + 1]);
4234 newsrv->cklen = strlen(args[cur_arg + 1]);
4235 cur_arg += 2;
4236 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004237 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004238 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4239 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4240 cur_arg += 2;
4241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004243 if (!*args[cur_arg + 1]) {
4244 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4245 file, linenum, args[cur_arg]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004251 if (newsrv->rise <= 0) {
4252 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4253 file, linenum, args[cur_arg]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257
Willy Tarreau96839092010-03-29 10:02:24 +02004258 if (newsrv->health)
4259 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004260 cur_arg += 2;
4261 }
4262 else if (!strcmp(args[cur_arg], "fall")) {
4263 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004264
4265 if (!*args[cur_arg + 1]) {
4266 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4267 file, linenum, args[cur_arg]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 if (newsrv->fall <= 0) {
4273 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4274 file, linenum, args[cur_arg]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 cur_arg += 2;
4280 }
4281 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004282 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4283 if (err) {
4284 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4285 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004288 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004289 if (val <= 0) {
4290 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4291 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004294 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004295 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 cur_arg += 2;
4297 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004298 else if (!strcmp(args[cur_arg], "fastinter")) {
4299 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4300 if (err) {
4301 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4302 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004305 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004306 if (val <= 0) {
4307 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4308 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004311 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004312 newsrv->fastinter = val;
4313 cur_arg += 2;
4314 }
4315 else if (!strcmp(args[cur_arg], "downinter")) {
4316 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4317 if (err) {
4318 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4319 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004322 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004323 if (val <= 0) {
4324 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4325 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004328 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004329 newsrv->downinter = val;
4330 cur_arg += 2;
4331 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004332 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004333 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004334 if (!sk) {
4335 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004339 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004340 cur_arg += 2;
4341 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004343 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 cur_arg += 2;
4345 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004346 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 newsrv->state |= SRV_BACKUP;
4348 cur_arg ++;
4349 }
Simon Hormanfa461682011-06-25 09:39:49 +09004350 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4351 newsrv->state |= SRV_NON_STICK;
4352 cur_arg ++;
4353 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004354 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4355 newsrv->state |= SRV_SEND_PROXY;
4356 cur_arg ++;
4357 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004358 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4359 newsrv->check.send_proxy = 1;
4360 cur_arg ++;
4361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 else if (!strcmp(args[cur_arg], "weight")) {
4363 int w;
4364 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004365 if (w < 0 || w > 256) {
4366 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004367 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004371 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 cur_arg += 2;
4373 }
4374 else if (!strcmp(args[cur_arg], "minconn")) {
4375 newsrv->minconn = atol(args[cur_arg + 1]);
4376 cur_arg += 2;
4377 }
4378 else if (!strcmp(args[cur_arg], "maxconn")) {
4379 newsrv->maxconn = atol(args[cur_arg + 1]);
4380 cur_arg += 2;
4381 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004382 else if (!strcmp(args[cur_arg], "maxqueue")) {
4383 newsrv->maxqueue = atol(args[cur_arg + 1]);
4384 cur_arg += 2;
4385 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004386 else if (!strcmp(args[cur_arg], "slowstart")) {
4387 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004388 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004389 if (err) {
4390 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4391 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004394 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004395 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004396 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4397 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004400 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004401 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004402 cur_arg += 2;
4403 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004404 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004405
4406 if (!*args[cur_arg + 1]) {
4407 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4408 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004411 }
4412
4413 newsrv->trackit = strdup(args[cur_arg + 1]);
4414
4415 cur_arg += 2;
4416 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004417 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 global.maxsock++;
4419 do_check = 1;
4420 cur_arg += 1;
4421 }
Willy Tarreau96839092010-03-29 10:02:24 +02004422 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4423 newsrv->state |= SRV_MAINTAIN;
4424 newsrv->state &= ~SRV_RUNNING;
4425 newsrv->health = 0;
4426 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004427 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004428 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004429 if (!strcmp(args[cur_arg + 1], "none"))
4430 newsrv->observe = HANA_OBS_NONE;
4431 else if (!strcmp(args[cur_arg + 1], "layer4"))
4432 newsrv->observe = HANA_OBS_LAYER4;
4433 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4434 if (curproxy->mode != PR_MODE_HTTP) {
4435 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4436 file, linenum, args[cur_arg + 1]);
4437 err_code |= ERR_ALERT;
4438 }
4439 newsrv->observe = HANA_OBS_LAYER7;
4440 }
4441 else {
4442 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004443 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004444 file, linenum, args[cur_arg], args[cur_arg + 1]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
4448
4449 cur_arg += 2;
4450 }
4451 else if (!strcmp(args[cur_arg], "on-error")) {
4452 if (!strcmp(args[cur_arg + 1], "fastinter"))
4453 newsrv->onerror = HANA_ONERR_FASTINTER;
4454 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4455 newsrv->onerror = HANA_ONERR_FAILCHK;
4456 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4457 newsrv->onerror = HANA_ONERR_SUDDTH;
4458 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4459 newsrv->onerror = HANA_ONERR_MARKDWN;
4460 else {
4461 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004462 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004463 file, linenum, args[cur_arg], args[cur_arg + 1]);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 }
4467
4468 cur_arg += 2;
4469 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004470 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4471 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4472 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4473 else {
4474 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4475 file, linenum, args[cur_arg], args[cur_arg + 1]);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
4479
4480 cur_arg += 2;
4481 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004482 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4483 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4484 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4485 else {
4486 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4487 file, linenum, args[cur_arg], args[cur_arg + 1]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
4491
4492 cur_arg += 2;
4493 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004494 else if (!strcmp(args[cur_arg], "error-limit")) {
4495 if (!*args[cur_arg + 1]) {
4496 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4497 file, linenum, args[cur_arg]);
4498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
4500 }
4501
4502 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4503
4504 if (newsrv->consecutive_errors_limit <= 0) {
4505 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4506 file, linenum, args[cur_arg]);
4507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
4509 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004510 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004511 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004512 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004513 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004514 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004515
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004517#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004518 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004519 file, linenum, "source", "usesrc");
4520#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004521 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004523#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 }
4527 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004528 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4529 if (!sk) {
4530 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
4533 }
4534 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004535
4536 if (port_low != port_high) {
4537 int i;
4538 if (port_low <= 0 || port_low > 65535 ||
4539 port_high <= 0 || port_high > 65535 ||
4540 port_low > port_high) {
4541 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4542 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004545 }
4546 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4547 for (i = 0; i < newsrv->sport_range->size; i++)
4548 newsrv->sport_range->ports[i] = port_low + i;
4549 }
4550
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 while (*(args[cur_arg])) {
4553 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004554#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4555#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4557 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4558 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004561 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004562#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004563 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004564 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004565 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004568 }
4569 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004570 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004571 newsrv->state |= SRV_TPROXY_CLI;
4572 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004573 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004574 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004575 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4576 char *name, *end;
4577
4578 name = args[cur_arg+1] + 7;
4579 while (isspace(*name))
4580 name++;
4581
4582 end = name;
4583 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4584 end++;
4585
4586 newsrv->state &= ~SRV_TPROXY_MASK;
4587 newsrv->state |= SRV_TPROXY_DYN;
4588 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4589 newsrv->bind_hdr_len = end - name;
4590 memcpy(newsrv->bind_hdr_name, name, end - name);
4591 newsrv->bind_hdr_name[end-name] = '\0';
4592 newsrv->bind_hdr_occ = -1;
4593
4594 /* now look for an occurrence number */
4595 while (isspace(*end))
4596 end++;
4597 if (*end == ',') {
4598 end++;
4599 name = end;
4600 if (*end == '-')
4601 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004602 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004603 end++;
4604 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4605 }
4606
4607 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4608 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4609 " occurrences values smaller than %d.\n",
4610 file, linenum, MAX_HDR_HISTORY);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004614 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004615 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004616 if (!sk) {
4617 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620 }
4621 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004622 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004623 }
4624 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004625#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004626 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004627#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004628 cur_arg += 2;
4629 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004631 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004632 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004635#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4636 } /* "usesrc" */
4637
4638 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4639#ifdef SO_BINDTODEVICE
4640 if (!*args[cur_arg + 1]) {
4641 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4642 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004645 }
4646 if (newsrv->iface_name)
4647 free(newsrv->iface_name);
4648
4649 newsrv->iface_name = strdup(args[cur_arg + 1]);
4650 newsrv->iface_len = strlen(newsrv->iface_name);
4651 global.last_checks |= LSTCHK_NETADM;
4652#else
4653 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4654 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004657#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004658 cur_arg += 2;
4659 continue;
4660 }
4661 /* this keyword in not an option of "source" */
4662 break;
4663 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004665 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004666 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4667 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004672 static int srv_dumped;
4673 struct srv_kw *kw;
4674 char *err;
4675
4676 kw = srv_find_kw(args[cur_arg]);
4677 if (kw) {
4678 char *err = NULL;
4679 int code;
4680
4681 if (!kw->parse) {
4682 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4683 file, linenum, args[0], args[1], args[cur_arg]);
4684 cur_arg += 1 + kw->skip ;
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
4688
4689 if (defsrv && !kw->default_ok) {
4690 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4691 file, linenum, args[0], args[1], args[cur_arg]);
4692 cur_arg += 1 + kw->skip ;
4693 err_code |= ERR_ALERT;
4694 continue;
4695 }
4696
4697 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4698 err_code |= code;
4699
4700 if (code) {
4701 if (err && *err) {
4702 indent_msg(&err, 2);
4703 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4704 }
4705 else
4706 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4707 file, linenum, args[0], args[1], args[cur_arg]);
4708 if (code & ERR_FATAL) {
4709 free(err);
4710 cur_arg += 1 + kw->skip;
4711 goto out;
4712 }
4713 }
4714 free(err);
4715 cur_arg += 1 + kw->skip;
4716 continue;
4717 }
4718
4719 err = NULL;
4720 if (!srv_dumped) {
4721 srv_dump_kws(&err);
4722 indent_msg(&err, 4);
4723 srv_dumped = 1;
4724 }
4725
4726 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4727 file, linenum, args[0], args[1], args[cur_arg],
4728 err ? " Registered keywords :" : "", err ? err : "");
4729 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004730
Willy Tarreau93893792009-07-23 13:19:11 +02004731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
4734 }
4735
4736 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004737 if (newsrv->trackit) {
4738 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4739 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004742 }
4743
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004744 /* If neither a port nor an addr was specified and no check transport
4745 * layer is forced, then the transport layer used by the checks is the
4746 * same as for the production traffic. Otherwise we use raw_sock by
4747 * default, unless one is specified.
4748 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004749 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004750#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004751 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004752#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004753 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4754 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004755 /* try to get the port from check.addr if check.port not set */
4756 if (!newsrv->check.port)
4757 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004758
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004759 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4760 newsrv->check.port = realport; /* by default */
4761 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004762 /* not yet valid, because no port was set on
4763 * the server either. We'll check if we have
4764 * a known port on the first listener.
4765 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004766 struct listener *l;
4767
4768 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004769 newsrv->check.port = get_host_port(&l->addr);
4770 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004771 break;
4772 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004773 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004774 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4776 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004780
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004781 /* Allocate buffer for check requests... */
4782 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004783 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4784 err_code |= ERR_ALERT | ERR_ABORT;
4785 goto out;
4786 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004787 newsrv->check.bi->size = global.tune.chksize;
4788
4789 /* Allocate buffer for check responses... */
4790 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4791 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4792 err_code |= ERR_ALERT | ERR_ABORT;
4793 goto out;
4794 }
4795 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004796
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004797 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004798 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004799 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4800 err_code |= ERR_ALERT | ERR_ABORT;
4801 goto out;
4802 }
4803
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004804 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4805 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 newsrv->state |= SRV_CHECKED;
4807 }
4808
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004809 if (!defsrv) {
4810 if (newsrv->state & SRV_BACKUP)
4811 curproxy->srv_bck++;
4812 else
4813 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004814
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004815 newsrv->prev_state = newsrv->state;
4816 }
William Lallemanda73203e2012-03-12 12:48:57 +01004817 }
4818
4819 else if (strcmp(args[0], "unique-id-format") == 0) {
4820 if (!*(args[1])) {
4821 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
William Lallemand3203ff42012-11-11 17:30:56 +01004825 if (*(args[2])) {
4826 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
4829 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004830 free(curproxy->uniqueid_format_string);
4831 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004832 }
William Lallemanda73203e2012-03-12 12:48:57 +01004833
4834 else if (strcmp(args[0], "unique-id-header") == 0) {
4835 if (!*(args[1])) {
4836 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
4839 }
4840 free(curproxy->header_unique_id);
4841 curproxy->header_unique_id = strdup(args[1]);
4842 }
4843
William Lallemand723b73a2012-02-08 16:37:49 +01004844 else if (strcmp(args[0], "log-format") == 0) {
4845 if (!*(args[1])) {
4846 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
William Lallemand3203ff42012-11-11 17:30:56 +01004850 if (*(args[2])) {
4851 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004855
4856 if (curproxy->logformat_string != default_http_log_format &&
4857 curproxy->logformat_string != default_tcp_log_format &&
4858 curproxy->logformat_string != clf_http_log_format)
4859 free(curproxy->logformat_string);
4860 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 }
William Lallemand723b73a2012-02-08 16:37:49 +01004862
William Lallemand0f99e342011-10-12 17:50:54 +02004863 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4864 /* delete previous herited or defined syslog servers */
4865 struct logsrv *back;
4866
4867 if (*(args[1]) != 0) {
4868 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872
William Lallemand723b73a2012-02-08 16:37:49 +01004873 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4874 LIST_DEL(&tmplogsrv->list);
4875 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004876 }
4877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004879 struct logsrv *logsrv;
4880
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004882 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004883 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004884 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004885 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004886 LIST_INIT(&node->list);
4887 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 }
4890 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004891
4892 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893
William Lallemand0f99e342011-10-12 17:50:54 +02004894 logsrv->facility = get_log_facility(args[2]);
4895 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
4899
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901
William Lallemand0f99e342011-10-12 17:50:54 +02004902 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004904 logsrv->level = get_log_level(args[3]);
4905 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
4911 }
4912
William Lallemand0f99e342011-10-12 17:50:54 +02004913 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004914 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004915 logsrv->minlvl = get_log_level(args[4]);
4916 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004917 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
4920
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004921 }
4922 }
4923
Robert Tsai81ae1952007-12-05 10:47:29 +01004924 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004925 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004926 if (!sk) {
4927 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004928 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931 }
William Lallemand0f99e342011-10-12 17:50:54 +02004932 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004933 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004934 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004935 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004936 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
William Lallemand0f99e342011-10-12 17:50:54 +02004940 logsrv->addr = *sk;
4941 if (!get_host_port(&logsrv->addr))
4942 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
William Lallemand0f99e342011-10-12 17:50:54 +02004944
4945 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 else {
4948 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4949 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 }
4954 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004955 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004956 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004957
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004962 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4963 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004967
4968 /* we must first clear any optional default setting */
4969 curproxy->options &= ~PR_O_TPXY_MASK;
4970 free(curproxy->iface_name);
4971 curproxy->iface_name = NULL;
4972 curproxy->iface_len = 0;
4973
Willy Tarreaud5191e72010-02-09 20:50:45 +01004974 sk = str2sa(args[1]);
4975 if (!sk) {
4976 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
4979 }
4980 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004982
4983 cur_arg = 2;
4984 while (*(args[cur_arg])) {
4985 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004986#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4987#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004988 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4989 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4990 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004993 }
4994#endif
4995 if (!*args[cur_arg + 1]) {
4996 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4997 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005000 }
5001
5002 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005003 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005004 curproxy->options |= PR_O_TPXY_CLI;
5005 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005006 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005007 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005008 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5009 char *name, *end;
5010
5011 name = args[cur_arg+1] + 7;
5012 while (isspace(*name))
5013 name++;
5014
5015 end = name;
5016 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5017 end++;
5018
5019 curproxy->options &= ~PR_O_TPXY_MASK;
5020 curproxy->options |= PR_O_TPXY_DYN;
5021 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5022 curproxy->bind_hdr_len = end - name;
5023 memcpy(curproxy->bind_hdr_name, name, end - name);
5024 curproxy->bind_hdr_name[end-name] = '\0';
5025 curproxy->bind_hdr_occ = -1;
5026
5027 /* now look for an occurrence number */
5028 while (isspace(*end))
5029 end++;
5030 if (*end == ',') {
5031 end++;
5032 name = end;
5033 if (*end == '-')
5034 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005035 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005036 end++;
5037 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5038 }
5039
5040 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5041 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5042 " occurrences values smaller than %d.\n",
5043 file, linenum, MAX_HDR_HISTORY);
5044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
5046 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005047 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005048 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005049 if (!sk) {
5050 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
5054 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005055 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005056 }
5057 global.last_checks |= LSTCHK_NETADM;
5058#if !defined(CONFIG_HAP_LINUX_TPROXY)
5059 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005060#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005061#else /* no TPROXY support */
5062 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005063 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066#endif
5067 cur_arg += 2;
5068 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005069 }
5070
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5072#ifdef SO_BINDTODEVICE
5073 if (!*args[cur_arg + 1]) {
5074 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5075 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005078 }
5079 if (curproxy->iface_name)
5080 free(curproxy->iface_name);
5081
5082 curproxy->iface_name = strdup(args[cur_arg + 1]);
5083 curproxy->iface_len = strlen(curproxy->iface_name);
5084 global.last_checks |= LSTCHK_NETADM;
5085#else
5086 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5087 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005090#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005091 cur_arg += 2;
5092 continue;
5093 }
5094 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005095 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005100 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5101 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5102 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113
5114 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005115 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005116 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
5120 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005122 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005123 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005129 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005130 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
5134 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005136 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005137 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
5141 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005143 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005144 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005148 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005150 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005151 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005153 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005154 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005155 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005158 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005161 }
5162 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005164 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005165 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005167 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5172 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176
5177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005178 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005179 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 }
5183 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005185 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005186 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 }
5190 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005192 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005193 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
5197 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005198 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005199 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005200 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 }
5204 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005205 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005206 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005207 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005211 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005213 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005214 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005216 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005219 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005220
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 if (curproxy == &defproxy) {
5222 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005226 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 if (*(args[1]) == 0) {
5230 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005234
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005235 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005236 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5237 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5238 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241 }
5242 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5243 }
5244 else if (*args[2]) {
5245 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5246 file, linenum, args[0], args[2]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005251 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005252 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005253 wl->s = strdup(args[1]);
5254 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005255 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
5257 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005261 err_code |= ERR_ALERT | ERR_FATAL;
5262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005264
Willy Tarreauade5ec42010-01-28 19:33:49 +01005265 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005266 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005267 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 }
5271 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005273 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005274 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
5278 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005280 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005281 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 }
5285 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5288 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
5292
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005294 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005295 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005301 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005302 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
5306 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005308 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005309 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005314 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005315
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 if (curproxy == &defproxy) {
5317 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005321 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005322 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if (*(args[1]) == 0) {
5325 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", 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 }
5329
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005331 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5332 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5333 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337 err_code |= warnif_cond_requires_req(cond, file, linenum);
5338 }
5339 else if (*args[2]) {
5340 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5341 file, linenum, args[0], args[2]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005346 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005347 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348 wl->s = strdup(args[1]);
5349 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 }
5351 else if (!strcmp(args[0], "errorloc") ||
5352 !strcmp(args[0], "errorloc302") ||
5353 !strcmp(args[0], "errorloc303")) { /* error location */
5354 int errnum, errlen;
5355 char *err;
5356
Willy Tarreau977b8e42006-12-29 14:19:17 +01005357 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005359
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005361 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
5365
5366 errnum = atol(args[1]);
5367 if (!strcmp(args[0], "errorloc303")) {
5368 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5369 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5370 } else {
5371 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5372 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5373 }
5374
Willy Tarreau0f772532006-12-23 20:51:41 +01005375 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5376 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005377 chunk_destroy(&curproxy->errmsg[rc]);
5378 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005379 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005382
5383 if (rc >= HTTP_ERR_SIZE) {
5384 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5385 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 free(err);
5387 }
5388 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005389 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5390 int errnum, errlen, fd;
5391 char *err;
5392 struct stat stat;
5393
5394 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005396
5397 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005398 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005401 }
5402
5403 fd = open(args[2], O_RDONLY);
5404 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5405 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5406 file, linenum, args[2], args[1]);
5407 if (fd >= 0)
5408 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005411 }
5412
Willy Tarreau27a674e2009-08-17 07:23:33 +02005413 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005414 errlen = stat.st_size;
5415 } else {
5416 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005417 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005418 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005419 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005420 }
5421
5422 err = malloc(errlen); /* malloc() must succeed during parsing */
5423 errnum = read(fd, err, errlen);
5424 if (errnum != errlen) {
5425 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5426 file, linenum, args[2], args[1]);
5427 close(fd);
5428 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005431 }
5432 close(fd);
5433
5434 errnum = atol(args[1]);
5435 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5436 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005437 chunk_destroy(&curproxy->errmsg[rc]);
5438 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005439 break;
5440 }
5441 }
5442
5443 if (rc >= HTTP_ERR_SIZE) {
5444 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5445 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005446 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005447 free(err);
5448 }
5449 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005450 else if (!strcmp(args[0], "compression")) {
5451 struct comp *comp;
5452 if (curproxy->comp == NULL) {
5453 comp = calloc(1, sizeof(struct comp));
5454 curproxy->comp = comp;
5455 } else {
5456 comp = curproxy->comp;
5457 }
5458
5459 if (!strcmp(args[1], "algo")) {
5460 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005461 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005462
William Lallemand82fe75c2012-10-23 10:25:10 +02005463 cur_arg = 2;
5464 if (!*args[cur_arg]) {
5465 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5466 file, linenum, args[0]);
5467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
5470 while (*(args[cur_arg])) {
5471 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5472 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5473 file, linenum, args[0], args[cur_arg]);
5474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
5476 }
William Lallemand552df672012-11-07 13:21:47 +01005477 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5478 curproxy->comp->algos->end(&ctx);
5479 } else {
5480 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5481 file, linenum, args[0], args[cur_arg]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005485 cur_arg ++;
5486 continue;
5487 }
5488 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005489 else if (!strcmp(args[1], "offload")) {
5490 comp->offload = 1;
5491 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005492 else if (!strcmp(args[1], "type")) {
5493 int cur_arg;
5494 cur_arg = 2;
5495 if (!*args[cur_arg]) {
5496 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5497 file, linenum, args[0]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 }
5501 while (*(args[cur_arg])) {
5502 comp_append_type(comp, args[cur_arg]);
5503 cur_arg ++;
5504 continue;
5505 }
5506 }
5507 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005508 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005509 file, linenum, args[0]);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 }
5513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005515 struct cfg_kw_list *kwl;
5516 int index;
5517
5518 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5519 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5520 if (kwl->kw[index].section != CFG_LISTEN)
5521 continue;
5522 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5523 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005524 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005525 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005526 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005529 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005530 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005531 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005532 err_code |= ERR_WARN;
5533 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005534 }
Willy Tarreau93893792009-07-23 13:19:11 +02005535 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005536 }
5537 }
5538 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005539
Willy Tarreau6daf3432008-01-22 16:44:08 +01005540 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
Willy Tarreau93893792009-07-23 13:19:11 +02005544 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005545 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005546 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547}
5548
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005549int
5550cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5551{
5552
5553 int err_code = 0;
5554 const char *err;
5555
5556 if (!strcmp(args[0], "userlist")) { /* new userlist */
5557 struct userlist *newul;
5558
5559 if (!*args[1]) {
5560 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5561 file, linenum, args[0]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565
5566 err = invalid_char(args[1]);
5567 if (err) {
5568 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5569 file, linenum, *err, args[0], args[1]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573
5574 for (newul = userlist; newul; newul = newul->next)
5575 if (!strcmp(newul->name, args[1])) {
5576 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5577 file, linenum, args[1]);
5578 err_code |= ERR_WARN;
5579 goto out;
5580 }
5581
5582 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5583 if (!newul) {
5584 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5585 err_code |= ERR_ALERT | ERR_ABORT;
5586 goto out;
5587 }
5588
5589 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5590 newul->name = strdup(args[1]);
5591
5592 if (!newul->groupusers | !newul->name) {
5593 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5594 err_code |= ERR_ALERT | ERR_ABORT;
5595 goto out;
5596 }
5597
5598 newul->next = userlist;
5599 userlist = newul;
5600
5601 } else if (!strcmp(args[0], "group")) { /* new group */
5602 int cur_arg, i;
5603 const char *err;
5604
5605 if (!*args[1]) {
5606 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5607 file, linenum, args[0]);
5608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
5611
5612 err = invalid_char(args[1]);
5613 if (err) {
5614 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5615 file, linenum, *err, args[0], args[1]);
5616 err_code |= ERR_ALERT | ERR_FATAL;
5617 goto out;
5618 }
5619
5620 for(i = 0; i < userlist->grpcnt; i++)
5621 if (!strcmp(userlist->groups[i], args[1])) {
5622 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5623 file, linenum, args[1], userlist->name);
5624 err_code |= ERR_ALERT;
5625 goto out;
5626 }
5627
5628 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5629 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5630 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
5634
5635 cur_arg = 2;
5636
5637 while (*args[cur_arg]) {
5638 if (!strcmp(args[cur_arg], "users")) {
5639 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5640 cur_arg += 2;
5641 continue;
5642 } else {
5643 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5644 file, linenum, args[0]);
5645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
5647 }
5648 }
5649
5650 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5651 } else if (!strcmp(args[0], "user")) { /* new user */
5652 struct auth_users *newuser;
5653 int cur_arg;
5654
5655 if (!*args[1]) {
5656 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5657 file, linenum, args[0]);
5658 err_code |= ERR_ALERT | ERR_FATAL;
5659 goto out;
5660 }
5661
5662 for (newuser = userlist->users; newuser; newuser = newuser->next)
5663 if (!strcmp(newuser->user, args[1])) {
5664 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5665 file, linenum, args[1], userlist->name);
5666 err_code |= ERR_ALERT;
5667 goto out;
5668 }
5669
5670 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5671 if (!newuser) {
5672 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5673 err_code |= ERR_ALERT | ERR_ABORT;
5674 goto out;
5675 }
5676
5677 newuser->user = strdup(args[1]);
5678
5679 newuser->next = userlist->users;
5680 userlist->users = newuser;
5681
5682 cur_arg = 2;
5683
5684 while (*args[cur_arg]) {
5685 if (!strcmp(args[cur_arg], "password")) {
5686#ifndef CONFIG_HAP_CRYPT
5687 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5688 file, linenum);
5689 err_code |= ERR_ALERT;
5690#endif
5691 newuser->pass = strdup(args[cur_arg + 1]);
5692 cur_arg += 2;
5693 continue;
5694 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5695 newuser->pass = strdup(args[cur_arg + 1]);
5696 newuser->flags |= AU_O_INSECURE;
5697 cur_arg += 2;
5698 continue;
5699 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005700 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005701 cur_arg += 2;
5702 continue;
5703 } else {
5704 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5705 file, linenum, args[0]);
5706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
5708 }
5709 }
5710 } else {
5711 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 }
5714
5715out:
5716 return err_code;
5717}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718
5719/*
5720 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005721 * Returns the error code, 0 if OK, or any combination of :
5722 * - ERR_ABORT: must abort ASAP
5723 * - ERR_FATAL: we can continue parsing but not start the service
5724 * - ERR_WARN: a warning has been emitted
5725 * - ERR_ALERT: an alert has been emitted
5726 * Only the two first ones can stop processing, the two others are just
5727 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005729int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005731 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732 FILE *f;
5733 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005735 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 if ((f=fopen(file,"r")) == NULL)
5738 return -1;
5739
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005740 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005741 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005742 char *end;
5743 char *args[MAX_LINE_ARGS + 1];
5744 char *line = thisline;
5745
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 linenum++;
5747
5748 end = line + strlen(line);
5749
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005750 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5751 /* Check if we reached the limit and the last char is not \n.
5752 * Watch out for the last line without the terminating '\n'!
5753 */
5754 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005755 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005756 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005757 }
5758
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005760 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 line++;
5762
5763 arg = 0;
5764 args[arg] = line;
5765
5766 while (*line && arg < MAX_LINE_ARGS) {
5767 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5768 * C equivalent value. Other combinations left unchanged (eg: \1).
5769 */
5770 if (*line == '\\') {
5771 int skip = 0;
5772 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5773 *line = line[1];
5774 skip = 1;
5775 }
5776 else if (line[1] == 'r') {
5777 *line = '\r';
5778 skip = 1;
5779 }
5780 else if (line[1] == 'n') {
5781 *line = '\n';
5782 skip = 1;
5783 }
5784 else if (line[1] == 't') {
5785 *line = '\t';
5786 skip = 1;
5787 }
5788 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 unsigned char hex1, hex2;
5791 hex1 = toupper(line[2]) - '0';
5792 hex2 = toupper(line[3]) - '0';
5793 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5794 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5795 *line = (hex1<<4) + hex2;
5796 skip = 3;
5797 }
5798 else {
5799 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 }
5802 }
5803 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005804 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 end -= skip;
5806 }
5807 line++;
5808 }
5809 else if (*line == '#' || *line == '\n' || *line == '\r') {
5810 /* end of string, end of loop */
5811 *line = 0;
5812 break;
5813 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005814 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005816 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005817 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 line++;
5819 args[++arg] = line;
5820 }
5821 else {
5822 line++;
5823 }
5824 }
5825
5826 /* empty line */
5827 if (!**args)
5828 continue;
5829
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005830 if (*line) {
5831 /* we had to stop due to too many args.
5832 * Let's terminate the string, print the offending part then cut the
5833 * last arg.
5834 */
5835 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5836 line++;
5837 *line = '\0';
5838
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005839 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005840 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005841 err_code |= ERR_ALERT | ERR_FATAL;
5842 args[arg] = line;
5843 }
5844
Willy Tarreau540abe42007-05-02 20:50:16 +02005845 /* zero out remaining args and ensure that at least one entry
5846 * is zeroed out.
5847 */
5848 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 args[arg] = line;
5850 }
5851
Willy Tarreau3842f002009-06-14 11:39:52 +02005852 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005853 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005854 char *tmp;
5855
Willy Tarreau3842f002009-06-14 11:39:52 +02005856 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005857 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005858 for (arg=0; *args[arg+1]; arg++)
5859 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005860 *tmp = '\0'; // fix the next arg to \0
5861 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005862 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005863 else if (!strcmp(args[0], "default")) {
5864 kwm = KWM_DEF;
5865 for (arg=0; *args[arg+1]; arg++)
5866 args[arg] = args[arg+1]; // shift args after inversion
5867 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005868
William Lallemand0f99e342011-10-12 17:50:54 +02005869 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5870 strcmp(args[0], "log") != 0) {
5871 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005872 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005873 }
5874
Willy Tarreau977b8e42006-12-29 14:19:17 +01005875 if (!strcmp(args[0], "listen") ||
5876 !strcmp(args[0], "frontend") ||
5877 !strcmp(args[0], "backend") ||
5878 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005879 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005881 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005882 cursection = strdup(args[0]);
5883 }
5884 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005886 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005887 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005888 }
5889 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005890 confsect = CFG_USERLIST;
5891 free(cursection);
5892 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005893 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005894 else if (!strcmp(args[0], "peers")) {
5895 confsect = CFG_PEERS;
5896 free(cursection);
5897 cursection = strdup(args[0]);
5898 }
5899
Willy Tarreaubaaee002006-06-26 02:48:02 +02005900 /* else it's a section keyword */
5901
5902 switch (confsect) {
5903 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 break;
5906 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005907 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005909 case CFG_USERLIST:
5910 err_code |= cfg_parse_users(file, linenum, args, kwm);
5911 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005912 case CFG_PEERS:
5913 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5914 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005916 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005917 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005919
5920 if (err_code & ERR_ABORT)
5921 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005923 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005924 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005926 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005927}
5928
Willy Tarreaubb925012009-07-23 13:36:36 +02005929/*
5930 * Returns the error code, 0 if OK, or any combination of :
5931 * - ERR_ABORT: must abort ASAP
5932 * - ERR_FATAL: we can continue parsing but not start the service
5933 * - ERR_WARN: a warning has been emitted
5934 * - ERR_ALERT: an alert has been emitted
5935 * Only the two first ones can stop processing, the two others are just
5936 * indicators.
5937 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005938int check_config_validity()
5939{
5940 int cfgerr = 0;
5941 struct proxy *curproxy = NULL;
5942 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005943 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005944 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005945 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005946 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005948 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 /*
5950 * Now, check for the integrity of all that we have collected.
5951 */
5952
5953 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005954 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005955
Willy Tarreau193b8c62012-11-22 00:17:38 +01005956 if (!global.tune.max_http_hdr)
5957 global.tune.max_http_hdr = MAX_HTTP_HDR;
5958
5959 if (!global.tune.cookie_len)
5960 global.tune.cookie_len = CAPTURE_LEN;
5961
5962 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5963
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005964 /* first, we will invert the proxy list order */
5965 curproxy = NULL;
5966 while (proxy) {
5967 struct proxy *next;
5968
5969 next = proxy->next;
5970 proxy->next = curproxy;
5971 curproxy = proxy;
5972 if (!next)
5973 break;
5974 proxy = next;
5975 }
5976
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005978 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005979 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005980 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005981 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005982 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005983 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005984 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005985
Willy Tarreau050536d2012-10-04 08:47:34 +02005986 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005987 /* proxy ID not set, use automatic numbering with first
5988 * spare entry starting with next_pxid.
5989 */
5990 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5991 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5992 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005993 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005994 next_pxid++;
5995
Willy Tarreau55ea7572007-06-17 19:56:27 +02005996
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005998 /* ensure we don't keep listeners uselessly bound */
5999 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006000 curproxy = curproxy->next;
6001 continue;
6002 }
6003
Willy Tarreau16a21472012-11-19 12:39:59 +01006004 /* number of processes this proxy is bound to */
6005 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6006
Willy Tarreauff01a212009-03-15 13:46:16 +01006007 switch (curproxy->mode) {
6008 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006009 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006010 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006011 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6012 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006013 cfgerr++;
6014 }
6015
6016 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006017 Warning("config : servers will be ignored for %s '%s'.\n",
6018 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006019 break;
6020
6021 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006022 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006023 break;
6024
6025 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006026 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006027 break;
6028 }
6029
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006030 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006031 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006032 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006033 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6034 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006035 cfgerr++;
6036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006038 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006039 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6040 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006041 cfgerr++;
6042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006044 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006045 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6046 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006047 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006048 }
6049 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006050 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006051 /* If no LB algo is set in a backend, and we're not in
6052 * transparent mode, dispatch mode nor proxy mode, we
6053 * want to use balance roundrobin by default.
6054 */
6055 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6056 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057 }
6058 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006059
Willy Tarreau1620ec32011-08-06 17:05:02 +02006060 if (curproxy->options & PR_O_DISPATCH)
6061 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6062 else if (curproxy->options & PR_O_HTTP_PROXY)
6063 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6064 else if (curproxy->options & PR_O_TRANSP)
6065 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006066
Willy Tarreau1620ec32011-08-06 17:05:02 +02006067 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6068 if (curproxy->options & PR_O_DISABLE404) {
6069 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6070 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6071 err_code |= ERR_WARN;
6072 curproxy->options &= ~PR_O_DISABLE404;
6073 }
6074 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6075 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6076 "send-state", proxy_type_str(curproxy), curproxy->id);
6077 err_code |= ERR_WARN;
6078 curproxy->options &= ~PR_O2_CHK_SNDST;
6079 }
Willy Tarreauef781042010-01-27 11:53:01 +01006080 }
6081
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006082 /* if a default backend was specified, let's find it */
6083 if (curproxy->defbe.name) {
6084 struct proxy *target;
6085
Alex Williams96532db2009-11-01 21:27:13 -05006086 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006087 if (!target) {
6088 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6089 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006090 cfgerr++;
6091 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006092 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6093 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006094 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006095 } else {
6096 free(curproxy->defbe.name);
6097 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006098 /* we force the backend to be present on at least all of
6099 * the frontend's processes.
6100 */
6101 target->bind_proc = curproxy->bind_proc ?
6102 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006103
6104 /* Emit a warning if this proxy also has some servers */
6105 if (curproxy->srv) {
6106 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6107 curproxy->id);
6108 err_code |= ERR_WARN;
6109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 }
6111 }
6112
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006113 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006114 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6115 /* map jump target for ACT_SETBE in req_rep chain */
6116 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006117 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006118 struct proxy *target;
6119
Willy Tarreaua496b602006-12-17 23:15:24 +01006120 if (exp->action != ACT_SETBE)
6121 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006122
Alex Williams96532db2009-11-01 21:27:13 -05006123 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006124 if (!target) {
6125 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6126 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006127 cfgerr++;
6128 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006129 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6130 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006131 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006132 } else {
6133 free((void *)exp->replace);
6134 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006135 /* we force the backend to be present on at least all of
6136 * the frontend's processes.
6137 */
6138 target->bind_proc = curproxy->bind_proc ?
6139 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006140 }
6141 }
6142 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006143
6144 /* find the target proxy for 'use_backend' rules */
6145 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006146 struct proxy *target;
6147
Alex Williams96532db2009-11-01 21:27:13 -05006148 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006149
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006150 if (!target) {
6151 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6152 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006153 cfgerr++;
6154 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006155 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6156 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006157 cfgerr++;
6158 } else {
6159 free((void *)rule->be.name);
6160 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006161 /* we force the backend to be present on at least all of
6162 * the frontend's processes.
6163 */
6164 target->bind_proc = curproxy->bind_proc ?
6165 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006166 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006167 }
6168
6169 /* find the target proxy for 'use_backend' rules */
6170 list_for_each_entry(srule, &curproxy->server_rules, list) {
6171 struct server *target = findserver(curproxy, srule->srv.name);
6172
6173 if (!target) {
6174 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6175 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6176 cfgerr++;
6177 continue;
6178 }
6179 free((void *)srule->srv.name);
6180 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006181 }
6182
Emeric Brunb982a3d2010-01-04 15:45:53 +01006183 /* find the target table for 'stick' rules */
6184 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6185 struct proxy *target;
6186
Emeric Brun1d33b292010-01-04 15:47:17 +01006187 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6188 if (mrule->flags & STK_IS_STORE)
6189 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6190
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006192 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006193 else
6194 target = curproxy;
6195
6196 if (!target) {
6197 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6198 curproxy->id, mrule->table.name);
6199 cfgerr++;
6200 }
6201 else if (target->table.size == 0) {
6202 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6203 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6204 cfgerr++;
6205 }
Willy Tarreau12785782012-04-27 21:37:17 +02006206 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6207 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006208 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6209 cfgerr++;
6210 }
6211 else {
6212 free((void *)mrule->table.name);
6213 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006214 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006215 }
6216 }
6217
6218 /* find the target table for 'store response' rules */
6219 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6220 struct proxy *target;
6221
Emeric Brun1d33b292010-01-04 15:47:17 +01006222 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6223
Emeric Brunb982a3d2010-01-04 15:45:53 +01006224 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006225 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006226 else
6227 target = curproxy;
6228
6229 if (!target) {
6230 Alert("Proxy '%s': unable to find store table '%s'.\n",
6231 curproxy->id, mrule->table.name);
6232 cfgerr++;
6233 }
6234 else if (target->table.size == 0) {
6235 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6236 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6237 cfgerr++;
6238 }
Willy Tarreau12785782012-04-27 21:37:17 +02006239 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6240 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006241 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6242 cfgerr++;
6243 }
6244 else {
6245 free((void *)mrule->table.name);
6246 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006247 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006248 }
6249 }
6250
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006251 /* find the target table for 'tcp-request' layer 4 rules */
6252 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6253 struct proxy *target;
6254
Willy Tarreau56123282010-08-06 19:06:56 +02006255 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006256 continue;
6257
6258 if (trule->act_prm.trk_ctr.table.n)
6259 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6260 else
6261 target = curproxy;
6262
6263 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006264 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6265 curproxy->id, trule->act_prm.trk_ctr.table.n,
6266 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006267 cfgerr++;
6268 }
6269 else if (target->table.size == 0) {
6270 Alert("Proxy '%s': table '%s' used but not configured.\n",
6271 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6272 cfgerr++;
6273 }
6274 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006275 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006276 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6277 cfgerr++;
6278 }
6279 else {
6280 free(trule->act_prm.trk_ctr.table.n);
6281 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006282 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006283 * to pass a list of counters to track and allocate them right here using
6284 * stktable_alloc_data_type().
6285 */
6286 }
6287 }
6288
Willy Tarreaud1f96522010-08-03 19:34:32 +02006289 /* find the target table for 'tcp-request' layer 6 rules */
6290 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6291 struct proxy *target;
6292
Willy Tarreau56123282010-08-06 19:06:56 +02006293 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006294 continue;
6295
6296 if (trule->act_prm.trk_ctr.table.n)
6297 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6298 else
6299 target = curproxy;
6300
6301 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006302 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6303 curproxy->id, trule->act_prm.trk_ctr.table.n,
6304 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006305 cfgerr++;
6306 }
6307 else if (target->table.size == 0) {
6308 Alert("Proxy '%s': table '%s' used but not configured.\n",
6309 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6310 cfgerr++;
6311 }
6312 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006313 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006314 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6315 cfgerr++;
6316 }
6317 else {
6318 free(trule->act_prm.trk_ctr.table.n);
6319 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006320 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006321 * to pass a list of counters to track and allocate them right here using
6322 * stktable_alloc_data_type().
6323 */
6324 }
6325 }
6326
Emeric Brun32da3c42010-09-23 18:39:19 +02006327 if (curproxy->table.peers.name) {
6328 struct peers *curpeers = peers;
6329
6330 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6331 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6332 free((void *)curproxy->table.peers.name);
6333 curproxy->table.peers.p = peers;
6334 break;
6335 }
6336 }
6337
6338 if (!curpeers) {
6339 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6340 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006341 free((void *)curproxy->table.peers.name);
6342 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006343 cfgerr++;
6344 }
6345 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006346 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6347 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006348 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006349 cfgerr++;
6350 }
6351 }
6352
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006353 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006354 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006355 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6356 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6357 "proxy", curproxy->id);
6358 cfgerr++;
6359 goto out_uri_auth_compat;
6360 }
6361
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006362 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006363 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006364 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006365 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006366
Willy Tarreau95fa4692010-02-01 13:05:50 +01006367 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6368 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006369
6370 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006371 uri_auth_compat_req[i++] = "realm";
6372 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6373 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006374
Willy Tarreau95fa4692010-02-01 13:05:50 +01006375 uri_auth_compat_req[i++] = "unless";
6376 uri_auth_compat_req[i++] = "{";
6377 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6378 uri_auth_compat_req[i++] = "}";
6379 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006380
Willy Tarreauff011f22011-01-06 17:51:27 +01006381 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6382 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006383 cfgerr++;
6384 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006385 }
6386
Willy Tarreauff011f22011-01-06 17:51:27 +01006387 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006388
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389 if (curproxy->uri_auth->auth_realm) {
6390 free(curproxy->uri_auth->auth_realm);
6391 curproxy->uri_auth->auth_realm = NULL;
6392 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006393
6394 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006395 }
6396out_uri_auth_compat:
6397
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006398 cfgerr += acl_find_targets(curproxy);
6399
Willy Tarreau2738a142006-07-08 17:28:09 +02006400 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006401 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006402 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006403 (!curproxy->timeout.connect ||
6404 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006405 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006406 " | While not properly invalid, you will certainly encounter various problems\n"
6407 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006408 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006409 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006410 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006411 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006412
Willy Tarreau1fa31262007-12-03 00:36:16 +01006413 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6414 * We must still support older configurations, so let's find out whether those
6415 * parameters have been set or must be copied from contimeouts.
6416 */
6417 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006418 if (!curproxy->timeout.tarpit ||
6419 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006420 /* tarpit timeout not set. We search in the following order:
6421 * default.tarpit, curr.connect, default.connect.
6422 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006423 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006424 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006426 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006427 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006428 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006429 }
6430 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006431 (!curproxy->timeout.queue ||
6432 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006433 /* queue timeout not set. We search in the following order:
6434 * default.queue, curr.connect, default.connect.
6435 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006436 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006437 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006438 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006439 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006440 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006441 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006442 }
6443 }
6444
Willy Tarreau1620ec32011-08-06 17:05:02 +02006445 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006446 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6447 curproxy->check_req = (char *)malloc(curproxy->check_len);
6448 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006449 }
6450
Willy Tarreau193b8c62012-11-22 00:17:38 +01006451 /* ensure that cookie capture length is not too large */
6452 if (curproxy->capture_len >= global.tune.cookie_len) {
6453 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6454 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6455 err_code |= ERR_WARN;
6456 curproxy->capture_len = global.tune.cookie_len - 1;
6457 }
6458
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006459 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006460 if (curproxy->nb_req_cap) {
6461 if (curproxy->mode == PR_MODE_HTTP) {
6462 curproxy->req_cap_pool = create_pool("ptrcap",
6463 curproxy->nb_req_cap * sizeof(char *),
6464 MEM_F_SHARED);
6465 } else {
6466 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6467 proxy_type_str(curproxy), curproxy->id);
6468 err_code |= ERR_WARN;
6469 curproxy->to_log &= ~LW_REQHDR;
6470 curproxy->nb_req_cap = 0;
6471 }
6472 }
6473
6474 if (curproxy->nb_rsp_cap) {
6475 if (curproxy->mode == PR_MODE_HTTP) {
6476 curproxy->rsp_cap_pool = create_pool("ptrcap",
6477 curproxy->nb_rsp_cap * sizeof(char *),
6478 MEM_F_SHARED);
6479 } else {
6480 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6481 proxy_type_str(curproxy), curproxy->id);
6482 err_code |= ERR_WARN;
6483 curproxy->to_log &= ~LW_REQHDR;
6484 curproxy->nb_rsp_cap = 0;
6485 }
6486 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006487
Willy Tarreau196729e2012-05-31 19:30:26 +02006488 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006489 if (!(curproxy->cap & PR_CAP_FE)) {
6490 if (curproxy->logformat_string != default_http_log_format &&
6491 curproxy->logformat_string != default_tcp_log_format &&
6492 curproxy->logformat_string != clf_http_log_format)
6493 free(curproxy->logformat_string);
6494 curproxy->logformat_string = NULL;
6495 }
6496
Willy Tarreau196729e2012-05-31 19:30:26 +02006497 if (curproxy->logformat_string)
6498 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6499
6500 if (curproxy->uniqueid_format_string)
6501 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6502
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 /* first, we will invert the servers list order */
6504 newsrv = NULL;
6505 while (curproxy->srv) {
6506 struct server *next;
6507
6508 next = curproxy->srv->next;
6509 curproxy->srv->next = newsrv;
6510 newsrv = curproxy->srv;
6511 if (!next)
6512 break;
6513 curproxy->srv = next;
6514 }
6515
Willy Tarreaudd701652010-05-25 23:03:02 +02006516 /* assign automatic UIDs to servers which don't have one yet */
6517 next_id = 1;
6518 newsrv = curproxy->srv;
6519 while (newsrv != NULL) {
6520 if (!newsrv->puid) {
6521 /* server ID not set, use automatic numbering with first
6522 * spare entry starting with next_svid.
6523 */
6524 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6525 newsrv->conf.id.key = newsrv->puid = next_id;
6526 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6527 }
6528 next_id++;
6529 newsrv = newsrv->next;
6530 }
6531
Willy Tarreau20697042007-11-15 23:26:18 +01006532 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006533 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534
Willy Tarreau62c3be22012-01-20 13:12:32 +01006535 /*
6536 * If this server supports a maxconn parameter, it needs a dedicated
6537 * tasks to fill the emptied slots when a connection leaves.
6538 * Also, resolve deferred tracking dependency if needed.
6539 */
6540 newsrv = curproxy->srv;
6541 while (newsrv != NULL) {
6542 if (newsrv->minconn > newsrv->maxconn) {
6543 /* Only 'minconn' was specified, or it was higher than or equal
6544 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6545 * this will avoid further useless expensive computations.
6546 */
6547 newsrv->maxconn = newsrv->minconn;
6548 } else if (newsrv->maxconn && !newsrv->minconn) {
6549 /* minconn was not specified, so we set it to maxconn */
6550 newsrv->minconn = newsrv->maxconn;
6551 }
6552
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006553#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006554 if (newsrv->use_ssl || newsrv->check.use_ssl)
6555 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006556#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006557
Willy Tarreau62c3be22012-01-20 13:12:32 +01006558 if (newsrv->trackit) {
6559 struct proxy *px;
6560 struct server *srv;
6561 char *pname, *sname;
6562
6563 pname = newsrv->trackit;
6564 sname = strrchr(pname, '/');
6565
6566 if (sname)
6567 *sname++ = '\0';
6568 else {
6569 sname = pname;
6570 pname = NULL;
6571 }
6572
6573 if (pname) {
6574 px = findproxy(pname, PR_CAP_BE);
6575 if (!px) {
6576 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6577 proxy_type_str(curproxy), curproxy->id,
6578 newsrv->id, pname);
6579 cfgerr++;
6580 goto next_srv;
6581 }
6582 } else
6583 px = curproxy;
6584
6585 srv = findserver(px, sname);
6586 if (!srv) {
6587 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6588 proxy_type_str(curproxy), curproxy->id,
6589 newsrv->id, sname);
6590 cfgerr++;
6591 goto next_srv;
6592 }
6593
6594 if (!(srv->state & SRV_CHECKED)) {
6595 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6596 "tracking as it does not have checks enabled.\n",
6597 proxy_type_str(curproxy), curproxy->id,
6598 newsrv->id, px->id, srv->id);
6599 cfgerr++;
6600 goto next_srv;
6601 }
6602
6603 if (curproxy != px &&
6604 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6605 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6606 "tracking: disable-on-404 option inconsistency.\n",
6607 proxy_type_str(curproxy), curproxy->id,
6608 newsrv->id, px->id, srv->id);
6609 cfgerr++;
6610 goto next_srv;
6611 }
6612
6613 /* if the other server is forced disabled, we have to do the same here */
6614 if (srv->state & SRV_MAINTAIN) {
6615 newsrv->state |= SRV_MAINTAIN;
6616 newsrv->state &= ~SRV_RUNNING;
6617 newsrv->health = 0;
6618 }
6619
6620 newsrv->track = srv;
6621 newsrv->tracknext = srv->tracknext;
6622 srv->tracknext = newsrv;
6623
6624 free(newsrv->trackit);
6625 newsrv->trackit = NULL;
6626 }
6627 next_srv:
6628 newsrv = newsrv->next;
6629 }
6630
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006631 /* We have to initialize the server lookup mechanism depending
6632 * on what LB algorithm was choosen.
6633 */
6634
6635 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6636 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6637 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006638 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6639 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6640 init_server_map(curproxy);
6641 } else {
6642 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6643 fwrr_init_server_groups(curproxy);
6644 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006645 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006646
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006647 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006648 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6649 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6650 fwlc_init_server_tree(curproxy);
6651 } else {
6652 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6653 fas_init_server_tree(curproxy);
6654 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006655 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006656
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006657 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006658 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6659 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6660 chash_init_server_tree(curproxy);
6661 } else {
6662 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6663 init_server_map(curproxy);
6664 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006665 break;
6666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667
6668 if (curproxy->options & PR_O_LOGASAP)
6669 curproxy->to_log &= ~LW_BYTES;
6670
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006671 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006672 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006673 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6674 proxy_type_str(curproxy), curproxy->id);
6675 err_code |= ERR_WARN;
6676 }
6677
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006678 if (curproxy->mode != PR_MODE_HTTP) {
6679 int optnum;
6680
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006681 if (curproxy->uri_auth) {
6682 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6683 proxy_type_str(curproxy), curproxy->id);
6684 err_code |= ERR_WARN;
6685 curproxy->uri_auth = NULL;
6686 }
6687
Willy Tarreau87cf5142011-08-19 22:57:24 +02006688 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006689 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6690 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6691 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006692 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006693 }
6694
6695 if (curproxy->options & PR_O_ORGTO) {
6696 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6697 "originalto", proxy_type_str(curproxy), curproxy->id);
6698 err_code |= ERR_WARN;
6699 curproxy->options &= ~PR_O_ORGTO;
6700 }
6701
6702 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6703 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6704 (curproxy->cap & cfg_opts[optnum].cap) &&
6705 (curproxy->options & cfg_opts[optnum].val)) {
6706 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6707 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6708 err_code |= ERR_WARN;
6709 curproxy->options &= ~cfg_opts[optnum].val;
6710 }
6711 }
6712
6713 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6714 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6715 (curproxy->cap & cfg_opts2[optnum].cap) &&
6716 (curproxy->options2 & cfg_opts2[optnum].val)) {
6717 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6718 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6719 err_code |= ERR_WARN;
6720 curproxy->options2 &= ~cfg_opts2[optnum].val;
6721 }
6722 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006723
Willy Tarreauefa5f512010-03-30 20:13:29 +02006724#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006725 if (curproxy->bind_hdr_occ) {
6726 curproxy->bind_hdr_occ = 0;
6727 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6728 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6729 err_code |= ERR_WARN;
6730 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006731#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006732 }
6733
Willy Tarreaubaaee002006-06-26 02:48:02 +02006734 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006735 * ensure that we're not cross-dressing a TCP server into HTTP.
6736 */
6737 newsrv = curproxy->srv;
6738 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006739 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006740 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6741 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006742 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006743 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006744
Willy Tarreau0cec3312011-10-31 13:49:26 +01006745 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6746 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6747 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6748 err_code |= ERR_WARN;
6749 }
6750
Willy Tarreauefa5f512010-03-30 20:13:29 +02006751#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006752 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6753 newsrv->bind_hdr_occ = 0;
6754 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6755 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6756 err_code |= ERR_WARN;
6757 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006758#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006759 newsrv = newsrv->next;
6760 }
6761
Willy Tarreauc1a21672009-08-16 22:37:44 +02006762 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006763 if (!curproxy->accept)
6764 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006765
Willy Tarreauc1a21672009-08-16 22:37:44 +02006766 if (curproxy->tcp_req.inspect_delay ||
6767 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006768 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006769
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006770 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006771 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006772 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006773 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006774
6775 /* both TCP and HTTP must check switching rules */
6776 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6777 }
6778
6779 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006780 if (curproxy->tcp_req.inspect_delay ||
6781 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6782 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6783
Emeric Brun97679e72010-09-23 17:56:44 +02006784 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6785 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6786
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006787 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006788 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006789 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006790 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006791
6792 /* If the backend does requires RDP cookie persistence, we have to
6793 * enable the corresponding analyser.
6794 */
6795 if (curproxy->options2 & PR_O2_RDPC_PRST)
6796 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6797 }
6798
Emeric Brunc52962f2012-11-15 18:28:02 +01006799#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006800 /* Configure SSL for each bind line.
6801 * Note: if configuration fails at some point, the ->ctx member
6802 * remains NULL so that listeners can later detach.
6803 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006804 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006805 if (!bind_conf->is_ssl) {
6806 if (bind_conf->default_ctx) {
6807 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6808 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6809 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006810 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006811 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006812 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006813 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006814 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006815 cfgerr++;
6816 continue;
6817 }
6818
Emeric Brun4b3091e2012-09-24 15:48:52 +02006819 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006820 Alert("Unable to allocate SSL session cache.\n");
6821 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006822 continue;
6823 }
6824
Emeric Brunfc0421f2012-09-07 17:30:07 +02006825 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006826 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006827 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006828#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006829
Willy Tarreaue6b98942007-10-29 01:09:36 +01006830 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006831 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006832 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006833 if (!listener->luid) {
6834 /* listener ID not set, use automatic numbering with first
6835 * spare entry starting with next_luid.
6836 */
6837 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6838 listener->conf.id.key = listener->luid = next_id;
6839 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006840 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006841 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006842
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006843 /* enable separate counters */
6844 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6845 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006846 if (!listener->name)
6847 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006848 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006849
Willy Tarreaue6b98942007-10-29 01:09:36 +01006850 if (curproxy->options & PR_O_TCP_NOLING)
6851 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006852 if (!listener->maxconn)
6853 listener->maxconn = curproxy->maxconn;
6854 if (!listener->backlog)
6855 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006856 if (!listener->maxaccept)
6857 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6858
6859 /* we want to have an optimal behaviour on single process mode to
6860 * maximize the work at once, but in multi-process we want to keep
6861 * some fairness between processes, so we target half of the max
6862 * number of events to be balanced over all the processes the proxy
6863 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6864 * used to disable the limit.
6865 */
6866 if (listener->maxaccept > 0) {
6867 if (nbproc > 1)
6868 listener->maxaccept = (listener->maxaccept + 1) / 2;
6869 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6870 }
6871
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006872 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006873 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006874 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006875 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006876
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006877 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6878 listener->options |= LI_O_TCP_RULES;
6879
Willy Tarreaude3041d2010-05-31 10:56:17 +02006880 if (curproxy->mon_mask.s_addr)
6881 listener->options |= LI_O_CHK_MONNET;
6882
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006883 /* smart accept mode is automatic in HTTP mode */
6884 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006885 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006886 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6887 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006888 }
6889
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006890 /* Release unused SSL configs */
6891 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6892 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006893 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006894#ifdef USE_OPENSSL
6895 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006896 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006897 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006898 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006899 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006900#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006901 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006902
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006903 /* Check multi-process mode compatibility for the current proxy */
6904 if (global.nbproc > 1) {
6905 int nbproc = 0;
6906 if (curproxy->bind_proc) {
6907 int proc;
6908 for (proc = 0; proc < global.nbproc; proc++) {
6909 if (curproxy->bind_proc & (1 << proc)) {
6910 nbproc++;
6911 }
6912 }
6913 } else {
6914 nbproc = global.nbproc;
6915 }
6916 if (curproxy->table.peers.name) {
6917 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6918 curproxy->id);
6919 cfgerr++;
6920 }
6921 if (nbproc > 1) {
6922 if (curproxy->uri_auth) {
6923 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6924 curproxy->id);
6925 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6926 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6927 curproxy->id);
6928 }
6929 }
6930 if (curproxy->appsession_name) {
6931 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6932 curproxy->id);
6933 }
6934 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6935 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6936 curproxy->id);
6937 }
6938 }
6939 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006940
6941 /* create the task associated with the proxy */
6942 curproxy->task = task_new();
6943 if (curproxy->task) {
6944 curproxy->task->context = curproxy;
6945 curproxy->task->process = manage_proxy;
6946 /* no need to queue, it will be done automatically if some
6947 * listener gets limited.
6948 */
6949 curproxy->task->expire = TICK_ETERNITY;
6950 } else {
6951 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6952 curproxy->id);
6953 cfgerr++;
6954 }
6955
Willy Tarreaubaaee002006-06-26 02:48:02 +02006956 curproxy = curproxy->next;
6957 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006958
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006959 /* Check multi-process mode compatibility */
6960 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006961 if (global.stats_fe && !global.stats_fe->bind_proc) {
6962 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 +01006963 }
6964 }
6965
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006966 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6967 struct auth_users *curuser;
6968 int g;
6969
6970 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6971 unsigned int group_mask = 0;
6972 char *group = NULL;
6973
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006974 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006975 continue;
6976
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006977 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006978
6979 for (g = 0; g < curuserlist->grpcnt; g++)
6980 if (!strcmp(curuserlist->groups[g], group))
6981 break;
6982
6983 if (g == curuserlist->grpcnt) {
6984 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6985 curuserlist->name, group, curuser->user);
6986 err_code |= ERR_ALERT | ERR_FATAL;
6987 goto out;
6988 }
6989
6990 group_mask |= (1 << g);
6991 }
6992
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006993 free(curuser->u.groups);
6994 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006995 }
6996
6997 for (g = 0; g < curuserlist->grpcnt; g++) {
6998 char *user = NULL;
6999
7000 if (!curuserlist->groupusers[g])
7001 continue;
7002
7003 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7004 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7005 if (!strcmp(curuser->user, user))
7006 break;
7007
7008 if (!curuser) {
7009 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7010 curuserlist->name, user, curuserlist->groups[g]);
7011 err_code |= ERR_ALERT | ERR_FATAL;
7012 goto out;
7013 }
7014
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007015 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007016 }
7017
7018 free(curuserlist->groupusers[g]);
7019 }
7020
7021 free(curuserlist->groupusers);
7022
7023#ifdef DEBUG_AUTH
7024 for (g = 0; g < curuserlist->grpcnt; g++) {
7025 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7026
7027 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007028 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007029 fprintf(stderr, " %s", curuser->user);
7030 }
7031
7032 fprintf(stderr, "\n");
7033 }
7034#endif
7035
Willy Tarreaufbb78422011-06-05 15:38:35 +02007036 }
7037
7038 /* automatically compute fullconn if not set. We must not do it in the
7039 * loop above because cross-references are not yet fully resolved.
7040 */
7041 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7042 /* If <fullconn> is not set, let's set it to 10% of the sum of
7043 * the possible incoming frontend's maxconns.
7044 */
7045 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7046 struct proxy *fe;
7047 int total = 0;
7048
7049 /* sum up the number of maxconns of frontends which
7050 * reference this backend at least once or which are
7051 * the same one ('listen').
7052 */
7053 for (fe = proxy; fe; fe = fe->next) {
7054 struct switching_rule *rule;
7055 struct hdr_exp *exp;
7056 int found = 0;
7057
7058 if (!(fe->cap & PR_CAP_FE))
7059 continue;
7060
7061 if (fe == curproxy) /* we're on a "listen" instance */
7062 found = 1;
7063
7064 if (fe->defbe.be == curproxy) /* "default_backend" */
7065 found = 1;
7066
7067 /* check if a "use_backend" rule matches */
7068 if (!found) {
7069 list_for_each_entry(rule, &fe->switching_rules, list) {
7070 if (rule->be.backend == curproxy) {
7071 found = 1;
7072 break;
7073 }
7074 }
7075 }
7076
7077 /* check if a "reqsetbe" rule matches */
7078 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7079 if (exp->action == ACT_SETBE &&
7080 (struct proxy *)exp->replace == curproxy) {
7081 found = 1;
7082 break;
7083 }
7084 }
7085
7086 /* now we've checked all possible ways to reference a backend
7087 * from a frontend.
7088 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007089 if (!found)
7090 continue;
7091 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007092 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007093 /* we have the sum of the maxconns in <total>. We only
7094 * keep 10% of that sum to set the default fullconn, with
7095 * a hard minimum of 1 (to avoid a divide by zero).
7096 */
7097 curproxy->fullconn = (total + 9) / 10;
7098 if (!curproxy->fullconn)
7099 curproxy->fullconn = 1;
7100 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007101 }
7102
Willy Tarreau056f5682010-06-06 15:51:11 +02007103 /* initialize stick-tables on backend capable proxies. This must not
7104 * be done earlier because the data size may be discovered while parsing
7105 * other proxies.
7106 */
7107 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007108 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007109
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007110 /*
7111 * Recount currently required checks.
7112 */
7113
7114 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7115 int optnum;
7116
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007117 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7118 if (curproxy->options & cfg_opts[optnum].val)
7119 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007120
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007121 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7122 if (curproxy->options2 & cfg_opts2[optnum].val)
7123 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007124 }
7125
Willy Tarreau122541c2011-09-07 21:24:49 +02007126 if (peers) {
7127 struct peers *curpeers = peers, **last;
7128 struct peer *p, *pb;
7129
7130 /* Remove all peers sections which don't have a valid listener.
7131 * This can happen when a peers section is never referenced and
7132 * does not contain a local peer.
7133 */
7134 last = &peers;
7135 while (*last) {
7136 curpeers = *last;
7137 if (curpeers->peers_fe) {
7138 last = &curpeers->next;
7139 continue;
7140 }
7141
7142 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7143 curpeers->id, localpeer);
7144
7145 p = curpeers->remote;
7146 while (p) {
7147 pb = p->next;
7148 free(p->id);
7149 free(p);
7150 p = pb;
7151 }
7152
7153 /* Destroy and unlink this curpeers section.
7154 * Note: curpeers is backed up into *last.
7155 */
7156 free(curpeers->id);
7157 curpeers = curpeers->next;
7158 free(*last);
7159 *last = curpeers;
7160 }
7161 }
7162
Willy Tarreau34eb6712011-10-24 18:15:04 +02007163 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007164 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007165 MEM_F_SHARED);
7166
Willy Tarreaubb925012009-07-23 13:36:36 +02007167 if (cfgerr > 0)
7168 err_code |= ERR_ALERT | ERR_FATAL;
7169 out:
7170 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007171}
7172
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007173/*
7174 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7175 * parsing sessions.
7176 */
7177void cfg_register_keywords(struct cfg_kw_list *kwl)
7178{
7179 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7180}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007182/*
7183 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7184 */
7185void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7186{
7187 LIST_DEL(&kwl->list);
7188 LIST_INIT(&kwl->list);
7189}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007190
7191/*
7192 * Local variables:
7193 * c-indent-level: 8
7194 * c-basic-offset: 8
7195 * End:
7196 */