blob: 949114792faf97a07e8ae2acaca80dcba1304873 [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;
Willy Tarreau846257e2013-01-24 00:29:37 +01001512 free(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001513 goto out;
1514 }
1515
Willy Tarreaufab5a432011-03-04 15:31:53 +01001516 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001517 free(raddr);
1518 if (!sk) {
1519 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
1522 }
1523 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001524 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001525 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001526 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001527
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001528 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001529 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1530 file, linenum, newpeer->addr.ss_family, args[2]);
1531 err_code |= ERR_ALERT | ERR_FATAL;
1532 goto out;
1533 }
1534
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001535 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001536
1537 if (strcmp(newpeer->id, localpeer) == 0) {
1538 /* Current is local peer, it define a frontend */
1539 newpeer->local = 1;
1540
1541 if (!curpeers->peers_fe) {
1542 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1543 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1544 err_code |= ERR_ALERT | ERR_ABORT;
1545 goto out;
1546 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001547
Willy Tarreau237250c2011-07-29 01:49:03 +02001548 init_new_proxy(curpeers->peers_fe);
1549 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001550
1551 curpeers->peers_fe->last_change = now.tv_sec;
1552 curpeers->peers_fe->id = strdup(args[1]);
1553 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001554 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001555 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1556 curpeers->peers_fe->timeout.connect = 5000;
1557 curpeers->peers_fe->accept = peer_accept;
1558 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001559 curpeers->peers_fe->conf.file = strdup(file);
1560 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001561
1562 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1563
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001564 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1565 if (err_msg && *err_msg) {
1566 indent_msg(&err_msg, 2);
1567 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1568 }
1569 else
1570 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1571 file, linenum, args[0], args[1], args[2]);
1572 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001573 err_code |= ERR_FATAL;
1574 goto out;
1575 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001576
1577 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1578 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1579 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1580 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1581 l->accept = session_accept;
1582 l->handler = process_session;
1583 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1584 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1585 global.maxsock += l->maxconn;
1586 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001587 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001588 else {
1589 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1590 file, linenum, args[0], args[1],
1591 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1592 err_code |= ERR_FATAL;
1593 goto out;
1594 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001595 }
1596 } /* neither "peer" nor "peers" */
1597 else if (*args[0] != 0) {
1598 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603out:
1604 return err_code;
1605}
1606
1607
Willy Tarreau3842f002009-06-14 11:39:52 +02001608int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609{
1610 static struct proxy *curproxy = NULL;
1611 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001612 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001613 int rc;
1614 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001615 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001616 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001617 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001618 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001619 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620
Willy Tarreau977b8e42006-12-29 14:19:17 +01001621 if (!strcmp(args[0], "listen"))
1622 rc = PR_CAP_LISTEN;
1623 else if (!strcmp(args[0], "frontend"))
1624 rc = PR_CAP_FE | PR_CAP_RS;
1625 else if (!strcmp(args[0], "backend"))
1626 rc = PR_CAP_BE | PR_CAP_RS;
1627 else if (!strcmp(args[0], "ruleset"))
1628 rc = PR_CAP_RS;
1629 else
1630 rc = PR_CAP_NONE;
1631
1632 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 if (!*args[1]) {
1634 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1635 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_ABORT;
1638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001640
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001641 err = invalid_char(args[1]);
1642 if (err) {
1643 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1644 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001646 }
1647
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001648 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1649 /*
1650 * If there are two proxies with the same name only following
1651 * combinations are allowed:
1652 *
1653 * listen backend frontend ruleset
1654 * listen - - - -
1655 * backend - - OK -
1656 * frontend - OK - -
1657 * ruleset - - - -
1658 */
1659
1660 if (!strcmp(curproxy->id, args[1]) &&
1661 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1662 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001663 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1664 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1665 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001666 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001667 }
1668 }
1669
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1671 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_ABORT;
1673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001675
Willy Tarreau97cb7802010-01-03 20:23:58 +01001676 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 curproxy->next = proxy;
1678 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001679 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001680 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001681 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684
1685 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001687 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001688 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001689
Willy Tarreau4348fad2012-09-20 16:48:07 +02001690 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1691
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001692 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1693 if (err_msg && *err_msg) {
1694 indent_msg(&err_msg, 2);
1695 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1696 }
1697 else
1698 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1699 file, linenum, args[0], args[1], args[2]);
1700 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001706 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 }
1709
1710 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001711 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001712 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001713
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001716 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001717 curproxy->no_options = defproxy.no_options;
1718 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001719 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001720 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001721 curproxy->except_net = defproxy.except_net;
1722 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001723 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001724 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001726 if (defproxy.fwdfor_hdr_len) {
1727 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1728 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1729 }
1730
Willy Tarreaub86db342009-11-30 11:50:16 +01001731 if (defproxy.orgto_hdr_len) {
1732 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1733 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1734 }
1735
Mark Lamourinec2247f02012-01-04 13:02:01 -05001736 if (defproxy.server_id_hdr_len) {
1737 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1738 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1739 }
1740
Willy Tarreau977b8e42006-12-29 14:19:17 +01001741 if (curproxy->cap & PR_CAP_FE) {
1742 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001743 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001744 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001745
1746 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001747 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1748 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001749
1750 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
Willy Tarreau977b8e42006-12-29 14:19:17 +01001753 if (curproxy->cap & PR_CAP_BE) {
1754 curproxy->fullconn = defproxy.fullconn;
1755 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001757 if (defproxy.check_req) {
1758 curproxy->check_req = calloc(1, defproxy.check_len);
1759 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1760 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001761 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001763 if (defproxy.expect_str) {
1764 curproxy->expect_str = strdup(defproxy.expect_str);
1765 if (defproxy.expect_regex) {
1766 /* note: this regex is known to be valid */
1767 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1768 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1769 }
1770 }
1771
Willy Tarreau67402132012-05-31 20:40:20 +02001772 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 if (defproxy.cookie_name)
1774 curproxy->cookie_name = strdup(defproxy.cookie_name);
1775 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001776 if (defproxy.cookie_domain)
1777 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001778
Willy Tarreau31936852010-10-06 16:59:56 +02001779 if (defproxy.cookie_maxidle)
1780 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1781
1782 if (defproxy.cookie_maxlife)
1783 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1784
Emeric Brun647caf12009-06-30 17:57:00 +02001785 if (defproxy.rdp_cookie_name)
1786 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1787 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1788
Willy Tarreau01732802007-11-01 22:48:15 +01001789 if (defproxy.url_param_name)
1790 curproxy->url_param_name = strdup(defproxy.url_param_name);
1791 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001792
Benoitaffb4812009-03-25 13:02:10 +01001793 if (defproxy.hh_name)
1794 curproxy->hh_name = strdup(defproxy.hh_name);
1795 curproxy->hh_len = defproxy.hh_len;
1796 curproxy->hh_match_domain = defproxy.hh_match_domain;
1797
Willy Tarreauef9a3602012-12-08 22:29:20 +01001798 if (defproxy.conn_src.iface_name)
1799 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1800 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1801 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001804 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 if (defproxy.capture_name)
1806 curproxy->capture_name = strdup(defproxy.capture_name);
1807 curproxy->capture_namelen = defproxy.capture_namelen;
1808 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001812 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001813 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001814 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001815 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 curproxy->uri_auth = defproxy.uri_auth;
1817 curproxy->mon_net = defproxy.mon_net;
1818 curproxy->mon_mask = defproxy.mon_mask;
1819 if (defproxy.monitor_uri)
1820 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1821 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001822 if (defproxy.defbe.name)
1823 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001824
1825 /* get either a pointer to the logformat string or a copy of it */
1826 curproxy->logformat_string = defproxy.logformat_string;
1827 if (curproxy->logformat_string &&
1828 curproxy->logformat_string != default_http_log_format &&
1829 curproxy->logformat_string != default_tcp_log_format &&
1830 curproxy->logformat_string != clf_http_log_format)
1831 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001832 }
1833
1834 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001835 curproxy->timeout.connect = defproxy.timeout.connect;
1836 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001837 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001838 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001839 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001840 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001841 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001842 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001843 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001844 }
1845
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001847
1848 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001849 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001850 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001851 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001852 LIST_INIT(&node->list);
1853 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1854 }
1855
Willy Tarreau196729e2012-05-31 19:30:26 +02001856 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1857 if (curproxy->uniqueid_format_string)
1858 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001859
1860 /* copy default header unique id */
1861 if (defproxy.header_unique_id)
1862 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1863
William Lallemand82fe75c2012-10-23 10:25:10 +02001864 /* default compression options */
1865 if (defproxy.comp != NULL) {
1866 curproxy->comp = calloc(1, sizeof(struct comp));
1867 curproxy->comp->algos = defproxy.comp->algos;
1868 curproxy->comp->types = defproxy.comp->types;
1869 }
1870
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001872 curproxy->conf.used_listener_id = EB_ROOT;
1873 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001874
Willy Tarreau93893792009-07-23 13:19:11 +02001875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001876 }
1877 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1878 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001879 /* FIXME-20070101: we should do this too at the end of the
1880 * config parsing to free all default values.
1881 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001882 free(defproxy.check_req);
1883 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001884 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001885 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001886 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001887 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001888 free(defproxy.capture_name);
1889 free(defproxy.monitor_uri);
1890 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001891 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001892 free(defproxy.fwdfor_hdr_name);
1893 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001894 free(defproxy.orgto_hdr_name);
1895 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001896 free(defproxy.server_id_hdr_name);
1897 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001898 free(defproxy.expect_str);
1899 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001900
Willy Tarreau39b06652012-06-01 10:58:06 +02001901 if (defproxy.logformat_string != default_http_log_format &&
1902 defproxy.logformat_string != default_tcp_log_format &&
1903 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001904 free(defproxy.logformat_string);
1905
1906 free(defproxy.uniqueid_format_string);
1907
Willy Tarreaua534fea2008-08-03 12:19:50 +02001908 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001909 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001910
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 /* we cannot free uri_auth because it might already be used */
1912 init_default_instance();
1913 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001914 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
1917 else if (curproxy == NULL) {
1918 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923
1924 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001926 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001927 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001928 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (curproxy == &defproxy) {
1931 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001935 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937
Emeric Bruned760922010-10-22 17:59:25 +02001938 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001939 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001943 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001944
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001945 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001946 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001947
1948 /* NOTE: the following line might create several listeners if there
1949 * are comma-separated IPs or port ranges. So all further processing
1950 * will have to be applied to all listeners created after last_listen.
1951 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001952 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1953 if (err_msg && *err_msg) {
1954 indent_msg(&err_msg, 2);
1955 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1956 }
1957 else
1958 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1959 file, linenum, args[0], args[1]);
1960 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
1963 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001964
Willy Tarreau4348fad2012-09-20 16:48:07 +02001965 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1966 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001967 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001968 }
1969
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001970 cur_arg = 2;
1971 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001972 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001973 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001974 char *err;
1975
Willy Tarreau26982662012-09-12 23:17:10 +02001976 kw = bind_find_kw(args[cur_arg]);
1977 if (kw) {
1978 char *err = NULL;
1979 int code;
1980
1981 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001982 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1983 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001984 cur_arg += 1 + kw->skip ;
1985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
1987 }
1988
Willy Tarreau4348fad2012-09-20 16:48:07 +02001989 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001990 err_code |= code;
1991
1992 if (code) {
1993 if (err && *err) {
1994 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001995 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001996 }
1997 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001998 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1999 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002000 if (code & ERR_FATAL) {
2001 free(err);
2002 cur_arg += 1 + kw->skip;
2003 goto out;
2004 }
2005 }
2006 free(err);
2007 cur_arg += 1 + kw->skip;
2008 continue;
2009 }
2010
Willy Tarreau8638f482012-09-18 18:01:17 +02002011 err = NULL;
2012 if (!bind_dumped) {
2013 bind_dump_kws(&err);
2014 indent_msg(&err, 4);
2015 bind_dumped = 1;
2016 }
2017
2018 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2019 file, linenum, args[0], args[1], args[cur_arg],
2020 err ? " Registered keywords :" : "", err ? err : "");
2021 free(err);
2022
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_ALERT | ERR_FATAL;
2024 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002025 }
Willy Tarreau93893792009-07-23 13:19:11 +02002026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 }
2028 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2029 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2030 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002037
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 /* flush useless bits */
2039 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002042 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002045
Willy Tarreau1c47f852006-07-09 08:22:27 +02002046 if (!*args[1]) {
2047 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2048 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002051 }
2052
Willy Tarreaua534fea2008-08-03 12:19:50 +02002053 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002054 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002055 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002056 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002057 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2058
Willy Tarreau93893792009-07-23 13:19:11 +02002059 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2062 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2063 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2064 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2065 else {
2066 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 }
2070 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002071 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002072 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002073
2074 if (curproxy == &defproxy) {
2075 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002077 err_code |= ERR_ALERT | ERR_FATAL;
2078 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002079 }
2080
2081 if (!*args[1]) {
2082 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2083 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_ALERT | ERR_FATAL;
2085 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086 }
2087
2088 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002089 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002090
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002091 if (curproxy->uuid <= 0) {
2092 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002093 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002096 }
2097
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002098 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2099 if (node) {
2100 struct proxy *target = container_of(node, struct proxy, conf.id);
2101 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2102 file, linenum, proxy_type_str(curproxy), curproxy->id,
2103 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
2106 }
2107 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002108 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002109 else if (!strcmp(args[0], "description")) {
2110 int i, len=0;
2111 char *d;
2112
Cyril Bonté99ed3272010-01-24 23:29:44 +01002113 if (curproxy == &defproxy) {
2114 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2115 file, linenum, args[0]);
2116 err_code |= ERR_ALERT | ERR_FATAL;
2117 goto out;
2118 }
2119
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002120 if (!*args[1]) {
2121 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2122 file, linenum, args[0]);
2123 return -1;
2124 }
2125
2126 for(i=1; *args[i]; i++)
2127 len += strlen(args[i])+1;
2128
2129 d = (char *)calloc(1, len);
2130 curproxy->desc = d;
2131
2132 d += sprintf(d, "%s", args[1]);
2133 for(i=2; *args[i]; i++)
2134 d += sprintf(d, " %s", args[i]);
2135
2136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2138 curproxy->state = PR_STSTOPPED;
2139 }
2140 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2141 curproxy->state = PR_STNEW;
2142 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002143 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2144 int cur_arg = 1;
2145 unsigned int set = 0;
2146
2147 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002148 unsigned int low, high;
2149
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002150 if (strcmp(args[cur_arg], "all") == 0) {
2151 set = 0;
2152 break;
2153 }
2154 else if (strcmp(args[cur_arg], "odd") == 0) {
2155 set |= 0x55555555;
2156 }
2157 else if (strcmp(args[cur_arg], "even") == 0) {
2158 set |= 0xAAAAAAAA;
2159 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002160 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002161 char *dash = strchr(args[cur_arg], '-');
2162
2163 low = high = str2uic(args[cur_arg]);
2164 if (dash)
2165 high = str2uic(dash + 1);
2166
2167 if (high < low) {
2168 unsigned int swap = low;
2169 low = high;
2170 high = swap;
2171 }
2172
2173 if (low < 1 || high > 32) {
2174 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002175 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002178 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002179
2180 if (high > global.nbproc) {
2181 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2182 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002184 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002185 while (low <= high)
2186 set |= 1 << (low++ - 1);
2187 }
2188 else {
2189 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2190 file, linenum, args[0]);
2191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002193 }
2194 cur_arg++;
2195 }
2196 curproxy->bind_proc = set;
2197 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002198 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002199 if (curproxy == &defproxy) {
2200 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002203 }
2204
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002205 err = invalid_char(args[1]);
2206 if (err) {
2207 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2208 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002210 }
2211
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002212 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2213 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2214 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002217 }
2218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2220 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 if (*(args[1]) == 0) {
2226 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2227 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002231
Willy Tarreau67402132012-05-31 20:40:20 +02002232 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002233 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002234 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 curproxy->cookie_name = strdup(args[1]);
2237 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002238
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 cur_arg = 2;
2240 while (*(args[cur_arg])) {
2241 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002242 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 }
2244 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002245 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246 }
2247 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002248 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
2250 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002251 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
2253 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002254 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002256 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002257 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002260 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002262 else if (!strcmp(args[cur_arg], "httponly")) {
2263 curproxy->ck_opts |= PR_CK_HTTPONLY;
2264 }
2265 else if (!strcmp(args[cur_arg], "secure")) {
2266 curproxy->ck_opts |= PR_CK_SECURE;
2267 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002268 else if (!strcmp(args[cur_arg], "domain")) {
2269 if (!*args[cur_arg + 1]) {
2270 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2271 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002274 }
2275
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002276 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002277 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002278 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2279 " dots nor does not start with a dot."
2280 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002282 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002283 }
2284
2285 err = invalid_domainchar(args[cur_arg + 1]);
2286 if (err) {
2287 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2288 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002291 }
2292
Willy Tarreau68a897b2009-12-03 23:28:34 +01002293 if (!curproxy->cookie_domain) {
2294 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2295 } else {
2296 /* one domain was already specified, add another one by
2297 * building the string which will be returned along with
2298 * the cookie.
2299 */
2300 char *new_ptr;
2301 int new_len = strlen(curproxy->cookie_domain) +
2302 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2303 new_ptr = malloc(new_len);
2304 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2305 free(curproxy->cookie_domain);
2306 curproxy->cookie_domain = new_ptr;
2307 }
Willy Tarreau31936852010-10-06 16:59:56 +02002308 cur_arg++;
2309 }
2310 else if (!strcmp(args[cur_arg], "maxidle")) {
2311 unsigned int maxidle;
2312 const char *res;
2313
2314 if (!*args[cur_arg + 1]) {
2315 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2316 file, linenum, args[cur_arg]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320
2321 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2322 if (res) {
2323 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2324 file, linenum, *res, args[cur_arg]);
2325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
2327 }
2328 curproxy->cookie_maxidle = maxidle;
2329 cur_arg++;
2330 }
2331 else if (!strcmp(args[cur_arg], "maxlife")) {
2332 unsigned int maxlife;
2333 const char *res;
2334
2335 if (!*args[cur_arg + 1]) {
2336 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2337 file, linenum, args[cur_arg]);
2338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
2340 }
2341
2342 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2343 if (res) {
2344 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2345 file, linenum, *res, args[cur_arg]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002350 cur_arg++;
2351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002353 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 +02002354 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
2358 cur_arg++;
2359 }
Willy Tarreau67402132012-05-31 20:40:20 +02002360 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2362 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365
Willy Tarreau67402132012-05-31 20:40:20 +02002366 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2368 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002371
Willy Tarreau67402132012-05-31 20:40:20 +02002372 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002373 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2374 file, linenum);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002378 else if (!strcmp(args[0], "persist")) { /* persist */
2379 if (*(args[1]) == 0) {
2380 Alert("parsing [%s:%d] : missing persist method.\n",
2381 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002384 }
2385
2386 if (!strncmp(args[1], "rdp-cookie", 10)) {
2387 curproxy->options2 |= PR_O2_RDPC_PRST;
2388
Emeric Brunb982a3d2010-01-04 15:45:53 +01002389 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002390 const char *beg, *end;
2391
2392 beg = args[1] + 11;
2393 end = strchr(beg, ')');
2394
2395 if (!end || end == beg) {
2396 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2397 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002400 }
2401
2402 free(curproxy->rdp_cookie_name);
2403 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2404 curproxy->rdp_cookie_len = end-beg;
2405 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002406 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002407 free(curproxy->rdp_cookie_name);
2408 curproxy->rdp_cookie_name = strdup("msts");
2409 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2410 }
2411 else { /* syntax */
2412 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2413 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002416 }
2417 }
2418 else {
2419 Alert("parsing [%s:%d] : unknown persist method.\n",
2420 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002421 err_code |= ERR_ALERT | ERR_FATAL;
2422 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002423 }
2424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002426 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002428 if (curproxy == &defproxy) {
2429 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002438 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002444 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 curproxy->appsession_name = strdup(args[1]);
2446 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2447 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002448 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2449 if (err) {
2450 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2451 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002454 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002455 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002456
Willy Tarreau51041c72007-09-09 21:56:53 +02002457 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2458 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_ABORT;
2460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002462
2463 cur_arg = 6;
2464 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002465 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2466 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002467 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002468 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002469 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002470 } else if (!strcmp(args[cur_arg], "prefix")) {
2471 curproxy->options2 |= PR_O2_AS_PFX;
2472 } else if (!strcmp(args[cur_arg], "mode")) {
2473 if (!*args[cur_arg + 1]) {
2474 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2475 file, linenum, args[0], args[cur_arg]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479
2480 cur_arg++;
2481 if (!strcmp(args[cur_arg], "query-string")) {
2482 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2483 curproxy->options2 |= PR_O2_AS_M_QS;
2484 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2485 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2486 curproxy->options2 |= PR_O2_AS_M_PP;
2487 } else {
2488 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002493 cur_arg++;
2494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 } /* Url App Session */
2496 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002497 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002499
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002501 if (curproxy == &defproxy) {
2502 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 if (*(args[4]) == 0) {
2508 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002513 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 curproxy->capture_name = strdup(args[2]);
2515 curproxy->capture_namelen = strlen(curproxy->capture_name);
2516 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 curproxy->to_log |= LW_COOKIE;
2518 }
2519 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2520 struct cap_hdr *hdr;
2521
2522 if (curproxy == &defproxy) {
2523 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 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 }
2527
2528 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2529 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2530 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 }
2534
2535 hdr = calloc(sizeof(struct cap_hdr), 1);
2536 hdr->next = curproxy->req_cap;
2537 hdr->name = strdup(args[3]);
2538 hdr->namelen = strlen(args[3]);
2539 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002540 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541 hdr->index = curproxy->nb_req_cap++;
2542 curproxy->req_cap = hdr;
2543 curproxy->to_log |= LW_REQHDR;
2544 }
2545 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2546 struct cap_hdr *hdr;
2547
2548 if (curproxy == &defproxy) {
2549 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 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553
2554 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2555 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2556 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
2560 hdr = calloc(sizeof(struct cap_hdr), 1);
2561 hdr->next = curproxy->rsp_cap;
2562 hdr->name = strdup(args[3]);
2563 hdr->namelen = strlen(args[3]);
2564 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002565 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 hdr->index = curproxy->nb_rsp_cap++;
2567 curproxy->rsp_cap = hdr;
2568 curproxy->to_log |= LW_RSPHDR;
2569 }
2570 else {
2571 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002578 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002580
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 if (*(args[1]) == 0) {
2582 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
2587 curproxy->conn_retries = atol(args[1]);
2588 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002589 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002590 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002591
2592 if (curproxy == &defproxy) {
2593 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
2596 }
2597
Willy Tarreau20b0de52012-12-24 15:45:22 +01002598 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2599 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2600 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2601 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2602 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2603 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002604 file, linenum, args[0]);
2605 err_code |= ERR_WARN;
2606 }
2607
Willy Tarreauff011f22011-01-06 17:51:27 +01002608 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002609
Willy Tarreauff011f22011-01-06 17:51:27 +01002610 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002611 err_code |= ERR_ALERT | ERR_ABORT;
2612 goto out;
2613 }
2614
Willy Tarreauff011f22011-01-06 17:51:27 +01002615 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2616 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002617 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002618 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2619 /* set the header name and length into the proxy structure */
2620 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2621 err_code |= ERR_WARN;
2622
2623 if (!*args[1]) {
2624 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2625 file, linenum, args[0]);
2626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
2628 }
2629
2630 /* set the desired header name */
2631 free(curproxy->server_id_hdr_name);
2632 curproxy->server_id_hdr_name = strdup(args[1]);
2633 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2634 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002635 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002636 if (curproxy == &defproxy) {
2637 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002640 }
2641
Willy Tarreauef6494c2010-01-28 17:12:36 +01002642 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002643 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002647 }
2648
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002649 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2650 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2651 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002654 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002655
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002656 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002657 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002658 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002659 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661
Cyril Bonté99ed3272010-01-24 23:29:44 +01002662 if (curproxy == &defproxy) {
2663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
Willy Tarreau4baae242012-12-27 12:00:31 +01002668 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2669 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2670 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002673 }
2674
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002675 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002676 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2677 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002679 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 struct switching_rule *rule;
2681
Willy Tarreaub099aca2008-10-12 17:26:37 +02002682 if (curproxy == &defproxy) {
2683 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002686 }
2687
Willy Tarreau55ea7572007-06-17 19:56:27 +02002688 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002690
2691 if (*(args[1]) == 0) {
2692 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002695 }
2696
Willy Tarreauef6494c2010-01-28 17:12:36 +01002697 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002698 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002702 }
2703
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002704 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2705 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2706 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709 }
2710
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002711 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002712
Willy Tarreau55ea7572007-06-17 19:56:27 +02002713 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2714 rule->cond = cond;
2715 rule->be.name = strdup(args[1]);
2716 LIST_INIT(&rule->list);
2717 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2718 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002719 else if (strcmp(args[0], "use-server") == 0) {
2720 struct server_rule *rule;
2721
2722 if (curproxy == &defproxy) {
2723 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
2726 }
2727
2728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2729 err_code |= ERR_WARN;
2730
2731 if (*(args[1]) == 0) {
2732 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736
2737 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2738 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2739 file, linenum, args[0]);
2740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
2742 }
2743
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002744 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2745 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2746 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
2750
2751 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2752
2753 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2754 rule->cond = cond;
2755 rule->srv.name = strdup(args[1]);
2756 LIST_INIT(&rule->list);
2757 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2758 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2759 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002760 else if ((!strcmp(args[0], "force-persist")) ||
2761 (!strcmp(args[0], "ignore-persist"))) {
2762 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002763
2764 if (curproxy == &defproxy) {
2765 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
2770 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2771 err_code |= ERR_WARN;
2772
Willy Tarreauef6494c2010-01-28 17:12:36 +01002773 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002774 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2775 file, linenum, args[0]);
2776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
2778 }
2779
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002780 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2781 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2782 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002787 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002788
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002789 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002790 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002791 if (!strcmp(args[0], "force-persist")) {
2792 rule->type = PERSIST_TYPE_FORCE;
2793 } else {
2794 rule->type = PERSIST_TYPE_IGNORE;
2795 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002796 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002797 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002798 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002799 else if (!strcmp(args[0], "stick-table")) {
2800 int myidx = 1;
2801
Emeric Brun32da3c42010-09-23 18:39:19 +02002802 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002803 curproxy->table.type = (unsigned int)-1;
2804 while (*args[myidx]) {
2805 const char *err;
2806
2807 if (strcmp(args[myidx], "size") == 0) {
2808 myidx++;
2809 if (!*(args[myidx])) {
2810 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2811 file, linenum, args[myidx-1]);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2816 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2817 file, linenum, *err, args[myidx-1]);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002821 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002822 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002823 else if (strcmp(args[myidx], "peers") == 0) {
2824 myidx++;
2825 if (!*(args[myidx])) {
2826 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2827 file, linenum, args[myidx-1]);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831 curproxy->table.peers.name = strdup(args[myidx++]);
2832 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002833 else if (strcmp(args[myidx], "expire") == 0) {
2834 myidx++;
2835 if (!*(args[myidx])) {
2836 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2837 file, linenum, args[myidx-1]);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
2841 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2842 if (err) {
2843 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2844 file, linenum, *err, args[myidx-1]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002849 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002850 }
2851 else if (strcmp(args[myidx], "nopurge") == 0) {
2852 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002853 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002854 }
2855 else if (strcmp(args[myidx], "type") == 0) {
2856 myidx++;
2857 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2858 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2859 file, linenum, args[myidx]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002863 /* myidx already points to next arg */
2864 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002865 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002866 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002867 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002868
2869 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002870 nw = args[myidx];
2871 while (*nw) {
2872 /* the "store" keyword supports a comma-separated list */
2873 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002874 sa = NULL; /* store arg */
2875 while (*nw && *nw != ',') {
2876 if (*nw == '(') {
2877 *nw = 0;
2878 sa = ++nw;
2879 while (*nw != ')') {
2880 if (!*nw) {
2881 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2882 file, linenum, args[0], cw);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886 nw++;
2887 }
2888 *nw = '\0';
2889 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002890 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002891 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002892 if (*nw)
2893 *nw++ = '\0';
2894 type = stktable_get_data_type(cw);
2895 if (type < 0) {
2896 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2897 file, linenum, args[0], cw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
Willy Tarreauac782882010-06-20 10:41:54 +02002901
2902 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2903 switch (err) {
2904 case PE_NONE: break;
2905 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002906 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2907 file, linenum, args[0], cw);
2908 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002909 break;
2910
2911 case PE_ARG_MISSING:
2912 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2913 file, linenum, args[0], cw);
2914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916
2917 case PE_ARG_NOT_USED:
2918 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2919 file, linenum, args[0], cw);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922
2923 default:
2924 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2925 file, linenum, args[0], cw);
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002928 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002929 }
2930 myidx++;
2931 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002932 else {
2933 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2934 file, linenum, args[myidx]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 }
2939
2940 if (!curproxy->table.size) {
2941 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2942 file, linenum);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
2947 if (curproxy->table.type == (unsigned int)-1) {
2948 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2949 file, linenum);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 }
2954 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002955 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002956 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 int myidx = 0;
2958 const char *name = NULL;
2959 int flags;
2960
2961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
2966
2967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2968 err_code |= ERR_WARN;
2969 goto out;
2970 }
2971
2972 myidx++;
2973 if ((strcmp(args[myidx], "store") == 0) ||
2974 (strcmp(args[myidx], "store-request") == 0)) {
2975 myidx++;
2976 flags = STK_IS_STORE;
2977 }
2978 else if (strcmp(args[myidx], "store-response") == 0) {
2979 myidx++;
2980 flags = STK_IS_STORE | STK_ON_RSP;
2981 }
2982 else if (strcmp(args[myidx], "match") == 0) {
2983 myidx++;
2984 flags = STK_IS_MATCH;
2985 }
2986 else if (strcmp(args[myidx], "on") == 0) {
2987 myidx++;
2988 flags = STK_IS_MATCH | STK_IS_STORE;
2989 }
2990 else {
2991 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
2996 if (*(args[myidx]) == 0) {
2997 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003002 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003003 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003004 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008
3009 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003010 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003011 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3012 file, linenum, args[0], expr->fetch->kw);
3013 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003014 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003015 goto out;
3016 }
3017 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003018 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3020 file, linenum, args[0], expr->fetch->kw);
3021 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003022 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003023 goto out;
3024 }
3025 }
3026
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003027 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3028 if (expr->fetch->cap & SMP_CAP_L7)
3029 curproxy->acl_requires |= ACL_USE_L7_ANY;
3030
Emeric Brunb982a3d2010-01-04 15:45:53 +01003031 if (strcmp(args[myidx], "table") == 0) {
3032 myidx++;
3033 name = args[myidx++];
3034 }
3035
Willy Tarreauef6494c2010-01-28 17:12:36 +01003036 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003037 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3038 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3039 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003041 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003042 goto out;
3043 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003045 else if (*(args[myidx])) {
3046 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3047 file, linenum, args[0], args[myidx]);
3048 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003049 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003050 goto out;
3051 }
Emeric Brun97679e72010-09-23 17:56:44 +02003052 if (flags & STK_ON_RSP)
3053 err_code |= warnif_cond_requires_req(cond, file, linenum);
3054 else
3055 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003056
Emeric Brunb982a3d2010-01-04 15:45:53 +01003057 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3058 rule->cond = cond;
3059 rule->expr = expr;
3060 rule->flags = flags;
3061 rule->table.name = name ? strdup(name) : NULL;
3062 LIST_INIT(&rule->list);
3063 if (flags & STK_ON_RSP)
3064 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3065 else
3066 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3067 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003069 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003071
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3073 curproxy->uri_auth = NULL; /* we must detach from the default config */
3074
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003075 if (!*args[1]) {
3076 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003077 } else if (!strcmp(args[1], "admin")) {
3078 struct stats_admin_rule *rule;
3079
3080 if (curproxy == &defproxy) {
3081 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
3085
3086 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3087 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3088 err_code |= ERR_ALERT | ERR_ABORT;
3089 goto out;
3090 }
3091
3092 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3093 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3094 file, linenum, args[0], args[1]);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003098 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3099 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3100 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
3105 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3106
3107 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3108 rule->cond = cond;
3109 LIST_INIT(&rule->list);
3110 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 } else if (!strcmp(args[1], "uri")) {
3112 if (*(args[2]) == 0) {
3113 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3117 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_ABORT;
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 }
3121 } else if (!strcmp(args[1], "realm")) {
3122 if (*(args[2]) == 0) {
3123 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3127 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_ABORT;
3129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003131 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003132 unsigned interval;
3133
3134 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3135 if (err) {
3136 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3137 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003140 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3141 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003144 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003145 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003146 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003147
3148 if (curproxy == &defproxy) {
3149 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
3152 }
3153
3154 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3155 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3156 err_code |= ERR_ALERT | ERR_ABORT;
3157 goto out;
3158 }
3159
Willy Tarreauff011f22011-01-06 17:51:27 +01003160 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3161 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003162 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3163 file, linenum, args[0]);
3164 err_code |= ERR_WARN;
3165 }
3166
Willy Tarreauff011f22011-01-06 17:51:27 +01003167 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003168
Willy Tarreauff011f22011-01-06 17:51:27 +01003169 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003170 err_code |= ERR_ALERT | ERR_ABORT;
3171 goto out;
3172 }
3173
Willy Tarreauff011f22011-01-06 17:51:27 +01003174 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3175 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003176
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 } else if (!strcmp(args[1], "auth")) {
3178 if (*(args[2]) == 0) {
3179 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_FATAL;
3181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3183 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_ABORT;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
3187 } else if (!strcmp(args[1], "scope")) {
3188 if (*(args[2]) == 0) {
3189 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_ABORT;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 } else if (!strcmp(args[1], "enable")) {
3198 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3199 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_ABORT;
3201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003203 } else if (!strcmp(args[1], "hide-version")) {
3204 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003208 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003209 } else if (!strcmp(args[1], "show-legends")) {
3210 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3211 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3212 err_code |= ERR_ALERT | ERR_ABORT;
3213 goto out;
3214 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003215 } else if (!strcmp(args[1], "show-node")) {
3216
3217 if (*args[2]) {
3218 int i;
3219 char c;
3220
3221 for (i=0; args[2][i]; i++) {
3222 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003223 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3224 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003225 break;
3226 }
3227
3228 if (!i || args[2][i]) {
3229 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3230 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3231 file, linenum, args[0], args[1]);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235 }
3236
3237 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3238 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
3241 }
3242 } else if (!strcmp(args[1], "show-desc")) {
3243 char *desc = NULL;
3244
3245 if (*args[2]) {
3246 int i, len=0;
3247 char *d;
3248
3249 for(i=2; *args[i]; i++)
3250 len += strlen(args[i])+1;
3251
3252 desc = d = (char *)calloc(1, len);
3253
3254 d += sprintf(d, "%s", args[2]);
3255 for(i=3; *args[i]; i++)
3256 d += sprintf(d, " %s", args[i]);
3257 }
3258
3259 if (!*args[2] && !global.desc)
3260 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3261 file, linenum, args[1]);
3262 else {
3263 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3264 free(desc);
3265 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3266 err_code |= ERR_ALERT | ERR_ABORT;
3267 goto out;
3268 }
3269 free(desc);
3270 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003272stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003273 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 +01003274 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 }
3278 }
3279 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003280 int optnum;
3281
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003282 if (*(args[1]) == '\0') {
3283 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3284 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003288
3289 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3290 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003291 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3292 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3293 file, linenum, cfg_opts[optnum].name);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
Willy Tarreau93893792009-07-23 13:19:11 +02003297 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3298 err_code |= ERR_WARN;
3299 goto out;
3300 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003301
Willy Tarreau3842f002009-06-14 11:39:52 +02003302 curproxy->no_options &= ~cfg_opts[optnum].val;
3303 curproxy->options &= ~cfg_opts[optnum].val;
3304
3305 switch (kwm) {
3306 case KWM_STD:
3307 curproxy->options |= cfg_opts[optnum].val;
3308 break;
3309 case KWM_NO:
3310 curproxy->no_options |= cfg_opts[optnum].val;
3311 break;
3312 case KWM_DEF: /* already cleared */
3313 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003314 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003315
Willy Tarreau93893792009-07-23 13:19:11 +02003316 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003317 }
3318 }
3319
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003320 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3321 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003322 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3323 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3324 file, linenum, cfg_opts2[optnum].name);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
Willy Tarreau93893792009-07-23 13:19:11 +02003328 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3329 err_code |= ERR_WARN;
3330 goto out;
3331 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003332
Willy Tarreau3842f002009-06-14 11:39:52 +02003333 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3334 curproxy->options2 &= ~cfg_opts2[optnum].val;
3335
3336 switch (kwm) {
3337 case KWM_STD:
3338 curproxy->options2 |= cfg_opts2[optnum].val;
3339 break;
3340 case KWM_NO:
3341 curproxy->no_options2 |= cfg_opts2[optnum].val;
3342 break;
3343 case KWM_DEF: /* already cleared */
3344 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003345 }
Willy Tarreau93893792009-07-23 13:19:11 +02003346 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003347 }
3348 }
3349
Willy Tarreau3842f002009-06-14 11:39:52 +02003350 if (kwm != KWM_STD) {
3351 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003352 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003355 }
3356
Emeric Brun3a058f32009-06-30 18:26:00 +02003357 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003358 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003360 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003361 if (*(args[2]) != '\0') {
3362 if (!strcmp(args[2], "clf")) {
3363 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003364 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003365 } else {
3366 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_ALERT | ERR_FATAL;
3368 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003369 }
3370 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003371 if (curproxy->logformat_string != default_http_log_format &&
3372 curproxy->logformat_string != default_tcp_log_format &&
3373 curproxy->logformat_string != clf_http_log_format)
3374 free(curproxy->logformat_string);
3375 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003376 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003377 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003379 if (curproxy->logformat_string != default_http_log_format &&
3380 curproxy->logformat_string != default_tcp_log_format &&
3381 curproxy->logformat_string != clf_http_log_format)
3382 free(curproxy->logformat_string);
3383 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 else if (!strcmp(args[1], "tcpka")) {
3386 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003387 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003388 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003389
3390 if (curproxy->cap & PR_CAP_FE)
3391 curproxy->options |= PR_O_TCP_CLI_KA;
3392 if (curproxy->cap & PR_CAP_BE)
3393 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 }
3395 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_WARN;
3398
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003400 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003401 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003402 curproxy->options2 &= ~PR_O2_CHK_ANY;
3403 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 if (!*args[2]) { /* no argument */
3405 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3406 curproxy->check_len = strlen(DEF_CHECK_REQ);
3407 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003408 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 curproxy->check_req = (char *)malloc(reqlen);
3410 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003411 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003413 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 if (*args[4])
3415 reqlen += strlen(args[4]);
3416 else
3417 reqlen += strlen("HTTP/1.0");
3418
3419 curproxy->check_req = (char *)malloc(reqlen);
3420 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003421 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003423 }
3424 else if (!strcmp(args[1], "ssl-hello-chk")) {
3425 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003426 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003428
Willy Tarreaua534fea2008-08-03 12:19:50 +02003429 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003430 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003431 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003432 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 }
Willy Tarreau23677902007-05-08 23:50:35 +02003434 else if (!strcmp(args[1], "smtpchk")) {
3435 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003436 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003437 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003438 curproxy->options2 &= ~PR_O2_CHK_ANY;
3439 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003440
3441 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3442 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3443 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3444 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3445 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3446 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3447 curproxy->check_req = (char *)malloc(reqlen);
3448 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3449 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3450 } else {
3451 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3452 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3453 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3454 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3455 }
3456 }
3457 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003458 else if (!strcmp(args[1], "pgsql-check")) {
3459 /* use PostgreSQL request to check servers' health */
3460 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3461 err_code |= ERR_WARN;
3462
3463 free(curproxy->check_req);
3464 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003465 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003466 curproxy->options2 |= PR_O2_PGSQL_CHK;
3467
3468 if (*(args[2])) {
3469 int cur_arg = 2;
3470
3471 while (*(args[cur_arg])) {
3472 if (strcmp(args[cur_arg], "user") == 0) {
3473 char * packet;
3474 uint32_t packet_len;
3475 uint32_t pv;
3476
3477 /* suboption header - needs additional argument for it */
3478 if (*(args[cur_arg+1]) == 0) {
3479 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3480 file, linenum, args[0], args[1], args[cur_arg]);
3481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
3483 }
3484
3485 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3486 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3487 pv = htonl(0x30000); /* protocol version 3.0 */
3488
3489 packet = (char*) calloc(1, packet_len);
3490
3491 memcpy(packet + 4, &pv, 4);
3492
3493 /* copy "user" */
3494 memcpy(packet + 8, "user", 4);
3495
3496 /* copy username */
3497 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3498
3499 free(curproxy->check_req);
3500 curproxy->check_req = packet;
3501 curproxy->check_len = packet_len;
3502
3503 packet_len = htonl(packet_len);
3504 memcpy(packet, &packet_len, 4);
3505 cur_arg += 2;
3506 } else {
3507 /* unknown suboption - catchall */
3508 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3509 file, linenum, args[0], args[1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513 } /* end while loop */
3514 }
3515 }
3516
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003517 else if (!strcmp(args[1], "redis-check")) {
3518 /* use REDIS PING request to check servers' health */
3519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3520 err_code |= ERR_WARN;
3521
3522 free(curproxy->check_req);
3523 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003524 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003525 curproxy->options2 |= PR_O2_REDIS_CHK;
3526
3527 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3528 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3529 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3530 }
3531
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003532 else if (!strcmp(args[1], "mysql-check")) {
3533 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003534 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3535 err_code |= ERR_WARN;
3536
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003537 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003538 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003539 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003540 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003541
3542 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3543 * const char mysql40_client_auth_pkt[] = {
3544 * "\x0e\x00\x00" // packet length
3545 * "\x01" // packet number
3546 * "\x00\x00" // client capabilities
3547 * "\x00\x00\x01" // max packet
3548 * "haproxy\x00" // username (null terminated string)
3549 * "\x00" // filler (always 0x00)
3550 * "\x01\x00\x00" // packet length
3551 * "\x00" // packet number
3552 * "\x01" // COM_QUIT command
3553 * };
3554 */
3555
3556 if (*(args[2])) {
3557 int cur_arg = 2;
3558
3559 while (*(args[cur_arg])) {
3560 if (strcmp(args[cur_arg], "user") == 0) {
3561 char *mysqluser;
3562 int packetlen, reqlen, userlen;
3563
3564 /* suboption header - needs additional argument for it */
3565 if (*(args[cur_arg+1]) == 0) {
3566 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3567 file, linenum, args[0], args[1], args[cur_arg]);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570 }
3571 mysqluser = args[cur_arg + 1];
3572 userlen = strlen(mysqluser);
3573 packetlen = userlen + 7;
3574 reqlen = packetlen + 9;
3575
3576 free(curproxy->check_req);
3577 curproxy->check_req = (char *)calloc(1, reqlen);
3578 curproxy->check_len = reqlen;
3579
3580 snprintf(curproxy->check_req, 4, "%c%c%c",
3581 ((unsigned char) packetlen & 0xff),
3582 ((unsigned char) (packetlen >> 8) & 0xff),
3583 ((unsigned char) (packetlen >> 16) & 0xff));
3584
3585 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003586 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003587 curproxy->check_req[8] = 1;
3588 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3589 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3590 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3591 cur_arg += 2;
3592 } else {
3593 /* unknown suboption - catchall */
3594 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3595 file, linenum, args[0], args[1]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 } /* end while loop */
3600 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003601 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003602 else if (!strcmp(args[1], "ldap-check")) {
3603 /* use LDAP request to check servers' health */
3604 free(curproxy->check_req);
3605 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003606 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003607 curproxy->options2 |= PR_O2_LDAP_CHK;
3608
3609 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3610 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3611 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3612 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003613 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003614 int cur_arg;
3615
3616 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3617 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003618 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003619
Willy Tarreau87cf5142011-08-19 22:57:24 +02003620 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003621
3622 free(curproxy->fwdfor_hdr_name);
3623 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3624 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3625
3626 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3627 cur_arg = 2;
3628 while (*(args[cur_arg])) {
3629 if (!strcmp(args[cur_arg], "except")) {
3630 /* suboption except - needs additional argument for it */
3631 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3632 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3633 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003636 }
3637 /* flush useless bits */
3638 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003639 cur_arg += 2;
3640 } else if (!strcmp(args[cur_arg], "header")) {
3641 /* suboption header - needs additional argument for it */
3642 if (*(args[cur_arg+1]) == 0) {
3643 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3644 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003647 }
3648 free(curproxy->fwdfor_hdr_name);
3649 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3650 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3651 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003652 } else if (!strcmp(args[cur_arg], "if-none")) {
3653 curproxy->options &= ~PR_O_FF_ALWAYS;
3654 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003655 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003656 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003657 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003658 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003661 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003662 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003663 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003664 else if (!strcmp(args[1], "originalto")) {
3665 int cur_arg;
3666
3667 /* insert x-original-to field, but not for the IP address listed as an except.
3668 * set default options (ie: bitfield, header name, etc)
3669 */
3670
3671 curproxy->options |= PR_O_ORGTO;
3672
3673 free(curproxy->orgto_hdr_name);
3674 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3675 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3676
Willy Tarreau87cf5142011-08-19 22:57:24 +02003677 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003678 cur_arg = 2;
3679 while (*(args[cur_arg])) {
3680 if (!strcmp(args[cur_arg], "except")) {
3681 /* suboption except - needs additional argument for it */
3682 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3684 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003687 }
3688 /* flush useless bits */
3689 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3690 cur_arg += 2;
3691 } else if (!strcmp(args[cur_arg], "header")) {
3692 /* suboption header - needs additional argument for it */
3693 if (*(args[cur_arg+1]) == 0) {
3694 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3695 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003698 }
3699 free(curproxy->orgto_hdr_name);
3700 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3701 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3702 cur_arg += 2;
3703 } else {
3704 /* unknown suboption - catchall */
3705 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3706 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003709 }
3710 } /* end while loop */
3711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 else {
3713 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
Willy Tarreau93893792009-07-23 13:19:11 +02003717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003719 else if (!strcmp(args[0], "default_backend")) {
3720 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003722
3723 if (*(args[1]) == 0) {
3724 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003727 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003728 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003729 curproxy->defbe.name = strdup(args[1]);
3730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003731 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003732 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003734
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003735 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3736 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 /* enable reconnections to dispatch */
3739 curproxy->options |= PR_O_REDISP;
3740 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003741 else if (!strcmp(args[0], "http-check")) {
3742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003744
3745 if (strcmp(args[1], "disable-on-404") == 0) {
3746 /* enable a graceful server shutdown on an HTTP 404 response */
3747 curproxy->options |= PR_O_DISABLE404;
3748 }
Willy Tarreauef781042010-01-27 11:53:01 +01003749 else if (strcmp(args[1], "send-state") == 0) {
3750 /* enable emission of the apparent state of a server in HTTP checks */
3751 curproxy->options2 |= PR_O2_CHK_SNDST;
3752 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003753 else if (strcmp(args[1], "expect") == 0) {
3754 const char *ptr_arg;
3755 int cur_arg;
3756
3757 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3758 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762
3763 cur_arg = 2;
3764 /* consider exclamation marks, sole or at the beginning of a word */
3765 while (*(ptr_arg = args[cur_arg])) {
3766 while (*ptr_arg == '!') {
3767 curproxy->options2 ^= PR_O2_EXP_INV;
3768 ptr_arg++;
3769 }
3770 if (*ptr_arg)
3771 break;
3772 cur_arg++;
3773 }
3774 /* now ptr_arg points to the beginning of a word past any possible
3775 * exclamation mark, and cur_arg is the argument which holds this word.
3776 */
3777 if (strcmp(ptr_arg, "status") == 0) {
3778 if (!*(args[cur_arg + 1])) {
3779 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3780 file, linenum, args[0], args[1], ptr_arg);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003785 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003786 curproxy->expect_str = strdup(args[cur_arg + 1]);
3787 }
3788 else if (strcmp(ptr_arg, "string") == 0) {
3789 if (!*(args[cur_arg + 1])) {
3790 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3791 file, linenum, args[0], args[1], ptr_arg);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
3794 }
3795 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003796 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003797 curproxy->expect_str = strdup(args[cur_arg + 1]);
3798 }
3799 else if (strcmp(ptr_arg, "rstatus") == 0) {
3800 if (!*(args[cur_arg + 1])) {
3801 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3802 file, linenum, args[0], args[1], ptr_arg);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003807 free(curproxy->expect_str);
3808 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3809 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003810 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3811 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3812 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3813 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
3816 }
3817 }
3818 else if (strcmp(ptr_arg, "rstring") == 0) {
3819 if (!*(args[cur_arg + 1])) {
3820 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3821 file, linenum, args[0], args[1], ptr_arg);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003826 free(curproxy->expect_str);
3827 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3828 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003829 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3830 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3831 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3832 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
3835 }
3836 }
3837 else {
3838 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3839 file, linenum, args[0], args[1], ptr_arg);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003844 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003845 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 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003848 }
3849 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003850 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003851 if (curproxy == &defproxy) {
3852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003855 }
3856
Willy Tarreaub80c2302007-11-30 20:51:32 +01003857 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003859
3860 if (strcmp(args[1], "fail") == 0) {
3861 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003862 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003863 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3864 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003867 }
3868
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003869 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3870 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3871 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003874 }
3875 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3876 }
3877 else {
3878 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003881 }
3882 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883#ifdef TPROXY
3884 else if (!strcmp(args[0], "transparent")) {
3885 /* enable transparent proxy connections */
3886 curproxy->options |= PR_O_TRANSP;
3887 }
3888#endif
3889 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003892
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 if (*(args[1]) == 0) {
3894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
3898 curproxy->maxconn = atol(args[1]);
3899 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003900 else if (!strcmp(args[0], "backlog")) { /* backlog */
3901 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003903
3904 if (*(args[1]) == 0) {
3905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003908 }
3909 curproxy->backlog = atol(args[1]);
3910 }
Willy Tarreau86034312006-12-29 00:10:33 +01003911 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003912 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003914
Willy Tarreau86034312006-12-29 00:10:33 +01003915 if (*(args[1]) == 0) {
3916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003919 }
3920 curproxy->fullconn = atol(args[1]);
3921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3923 if (*(args[1]) == 0) {
3924 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003928 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3929 if (err) {
3930 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3931 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003934 }
3935 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936 }
3937 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003938 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 if (curproxy == &defproxy) {
3940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003944 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003946
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 if (strchr(args[1], ':') == NULL) {
3948 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003952 sk = str2sa(args[1]);
3953 if (!sk) {
3954 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003959 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 }
3961 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003964
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003965 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3966 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003971 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3973 err_code |= ERR_WARN;
3974
3975 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3976 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3977 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3978 }
3979 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3980 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3981 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3982 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003983 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3984 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3985 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3986 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003987 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003988 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
3991 }
3992 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003993 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995 char *rport, *raddr;
3996 short realport = 0;
3997 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003999 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004004 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006
4007 if (!*args[2]) {
4008 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4009 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004010 err_code |= ERR_ALERT | ERR_FATAL;
4011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004013
4014 err = invalid_char(args[1]);
4015 if (err) {
4016 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4017 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004020 }
4021
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004023 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004024
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004025 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4026 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4027 err_code |= ERR_ALERT | ERR_ABORT;
4028 goto out;
4029 }
4030
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 /* the servers are linked backwards first */
4032 newsrv->next = curproxy->srv;
4033 curproxy->srv = newsrv;
4034 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004035 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004038 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004039 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004040 LIST_INIT(&newsrv->pendconns);
4041 do_check = 0;
4042 newsrv->state = SRV_RUNNING; /* early server setup */
4043 newsrv->last_change = now.tv_sec;
4044 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004045
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004047 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 * - IP: => port=+0, relative
4049 * - IP:N => port=N, absolute
4050 * - IP:+N => port=+N, relative
4051 * - IP:-N => port=-N, relative
4052 */
4053 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004054 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004055 if (rport) {
4056 *rport++ = 0;
4057 realport = atol(rport);
4058 if (!isdigit((unsigned char)*rport))
4059 newsrv->state |= SRV_MAPPORTS;
4060 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004062
Willy Tarreaufab5a432011-03-04 15:31:53 +01004063 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004064 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004065 if (!sk) {
4066 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004071 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4072 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004073
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004074 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004075 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4076 file, linenum, newsrv->addr.ss_family, args[2]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004080 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004081
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004082 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004083 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084 newsrv->inter = curproxy->defsrv.inter;
4085 newsrv->fastinter = curproxy->defsrv.fastinter;
4086 newsrv->downinter = curproxy->defsrv.downinter;
4087 newsrv->rise = curproxy->defsrv.rise;
4088 newsrv->fall = curproxy->defsrv.fall;
4089 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4090 newsrv->minconn = curproxy->defsrv.minconn;
4091 newsrv->maxconn = curproxy->defsrv.maxconn;
4092 newsrv->slowstart = curproxy->defsrv.slowstart;
4093 newsrv->onerror = curproxy->defsrv.onerror;
4094 newsrv->consecutive_errors_limit
4095 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004096#ifdef OPENSSL
4097 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4098#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004099 newsrv->uweight = newsrv->iweight
4100 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004104 cur_arg = 3;
4105 } else {
4106 newsrv = &curproxy->defsrv;
4107 cur_arg = 1;
4108 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004109
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004111 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112 newsrv->cookie = strdup(args[cur_arg + 1]);
4113 newsrv->cklen = strlen(args[cur_arg + 1]);
4114 cur_arg += 2;
4115 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004117 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4118 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4119 cur_arg += 2;
4120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004122 if (!*args[cur_arg + 1]) {
4123 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4124 file, linenum, args[cur_arg]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128
Willy Tarreaubaaee002006-06-26 02:48:02 +02004129 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004130 if (newsrv->rise <= 0) {
4131 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4132 file, linenum, args[cur_arg]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136
Willy Tarreau96839092010-03-29 10:02:24 +02004137 if (newsrv->health)
4138 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 cur_arg += 2;
4140 }
4141 else if (!strcmp(args[cur_arg], "fall")) {
4142 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004143
4144 if (!*args[cur_arg + 1]) {
4145 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4146 file, linenum, args[cur_arg]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150
4151 if (newsrv->fall <= 0) {
4152 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4153 file, linenum, args[cur_arg]);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 cur_arg += 2;
4159 }
4160 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004161 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4162 if (err) {
4163 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4164 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004167 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004168 if (val <= 0) {
4169 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4170 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004173 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004174 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 cur_arg += 2;
4176 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004177 else if (!strcmp(args[cur_arg], "fastinter")) {
4178 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4179 if (err) {
4180 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4181 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004184 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004185 if (val <= 0) {
4186 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4187 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004190 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004191 newsrv->fastinter = val;
4192 cur_arg += 2;
4193 }
4194 else if (!strcmp(args[cur_arg], "downinter")) {
4195 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4196 if (err) {
4197 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4198 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004201 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004202 if (val <= 0) {
4203 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4204 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004207 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004208 newsrv->downinter = val;
4209 cur_arg += 2;
4210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004212 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004213 if (!sk) {
4214 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004218 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004219 cur_arg += 2;
4220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004222 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 cur_arg += 2;
4224 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 newsrv->state |= SRV_BACKUP;
4227 cur_arg ++;
4228 }
Simon Hormanfa461682011-06-25 09:39:49 +09004229 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4230 newsrv->state |= SRV_NON_STICK;
4231 cur_arg ++;
4232 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004233 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4234 newsrv->state |= SRV_SEND_PROXY;
4235 cur_arg ++;
4236 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004237 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4238 newsrv->check.send_proxy = 1;
4239 cur_arg ++;
4240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 else if (!strcmp(args[cur_arg], "weight")) {
4242 int w;
4243 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004244 if (w < 0 || w > 256) {
4245 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004250 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 cur_arg += 2;
4252 }
4253 else if (!strcmp(args[cur_arg], "minconn")) {
4254 newsrv->minconn = atol(args[cur_arg + 1]);
4255 cur_arg += 2;
4256 }
4257 else if (!strcmp(args[cur_arg], "maxconn")) {
4258 newsrv->maxconn = atol(args[cur_arg + 1]);
4259 cur_arg += 2;
4260 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004261 else if (!strcmp(args[cur_arg], "maxqueue")) {
4262 newsrv->maxqueue = atol(args[cur_arg + 1]);
4263 cur_arg += 2;
4264 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004265 else if (!strcmp(args[cur_arg], "slowstart")) {
4266 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004267 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004268 if (err) {
4269 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4270 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004273 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004274 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004275 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4276 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004279 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004280 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004281 cur_arg += 2;
4282 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004283 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004284
4285 if (!*args[cur_arg + 1]) {
4286 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4287 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004290 }
4291
4292 newsrv->trackit = strdup(args[cur_arg + 1]);
4293
4294 cur_arg += 2;
4295 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004296 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 global.maxsock++;
4298 do_check = 1;
4299 cur_arg += 1;
4300 }
Willy Tarreau96839092010-03-29 10:02:24 +02004301 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4302 newsrv->state |= SRV_MAINTAIN;
4303 newsrv->state &= ~SRV_RUNNING;
4304 newsrv->health = 0;
4305 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004306 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004307 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004308 if (!strcmp(args[cur_arg + 1], "none"))
4309 newsrv->observe = HANA_OBS_NONE;
4310 else if (!strcmp(args[cur_arg + 1], "layer4"))
4311 newsrv->observe = HANA_OBS_LAYER4;
4312 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4313 if (curproxy->mode != PR_MODE_HTTP) {
4314 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4315 file, linenum, args[cur_arg + 1]);
4316 err_code |= ERR_ALERT;
4317 }
4318 newsrv->observe = HANA_OBS_LAYER7;
4319 }
4320 else {
4321 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004322 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004323 file, linenum, args[cur_arg], args[cur_arg + 1]);
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327
4328 cur_arg += 2;
4329 }
4330 else if (!strcmp(args[cur_arg], "on-error")) {
4331 if (!strcmp(args[cur_arg + 1], "fastinter"))
4332 newsrv->onerror = HANA_ONERR_FASTINTER;
4333 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4334 newsrv->onerror = HANA_ONERR_FAILCHK;
4335 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4336 newsrv->onerror = HANA_ONERR_SUDDTH;
4337 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4338 newsrv->onerror = HANA_ONERR_MARKDWN;
4339 else {
4340 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004341 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004342 file, linenum, args[cur_arg], args[cur_arg + 1]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346
4347 cur_arg += 2;
4348 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004349 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4350 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4351 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4352 else {
4353 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4354 file, linenum, args[cur_arg], args[cur_arg + 1]);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
4358
4359 cur_arg += 2;
4360 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004361 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4362 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4363 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4364 else {
4365 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4366 file, linenum, args[cur_arg], args[cur_arg + 1]);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370
4371 cur_arg += 2;
4372 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004373 else if (!strcmp(args[cur_arg], "error-limit")) {
4374 if (!*args[cur_arg + 1]) {
4375 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4376 file, linenum, args[cur_arg]);
4377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
4379 }
4380
4381 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4382
4383 if (newsrv->consecutive_errors_limit <= 0) {
4384 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4385 file, linenum, args[cur_arg]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004389 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004390 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004391 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004392 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004393 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004394
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004396 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4397 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004401 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004402 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4403 if (!sk) {
4404 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004408 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004409
4410 if (port_low != port_high) {
4411 int i;
4412 if (port_low <= 0 || port_low > 65535 ||
4413 port_high <= 0 || port_high > 65535 ||
4414 port_low > port_high) {
4415 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4416 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004419 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004420 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4421 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4422 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004423 }
4424
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 while (*(args[cur_arg])) {
4427 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4429#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004430 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004431 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4432 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004436#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004437 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004438 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004439 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442 }
4443 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004444 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4445 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004446 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004447 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4448 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004449 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4450 char *name, *end;
4451
4452 name = args[cur_arg+1] + 7;
4453 while (isspace(*name))
4454 name++;
4455
4456 end = name;
4457 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4458 end++;
4459
Willy Tarreauef9a3602012-12-08 22:29:20 +01004460 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4461 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4462 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4463 newsrv->conn_src.bind_hdr_len = end - name;
4464 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4465 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4466 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004467
4468 /* now look for an occurrence number */
4469 while (isspace(*end))
4470 end++;
4471 if (*end == ',') {
4472 end++;
4473 name = end;
4474 if (*end == '-')
4475 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004476 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004477 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004478 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004479 }
4480
Willy Tarreauef9a3602012-12-08 22:29:20 +01004481 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004482 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4483 " occurrences values smaller than %d.\n",
4484 file, linenum, MAX_HDR_HISTORY);
4485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
4487 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004488 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004489 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 if (!sk) {
4491 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004495 newsrv->conn_src.tproxy_addr = *sk;
4496 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004497 }
4498 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004499#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004500 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004501#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004502 cur_arg += 2;
4503 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004504#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004506 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004509#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4510 } /* "usesrc" */
4511
4512 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4513#ifdef SO_BINDTODEVICE
4514 if (!*args[cur_arg + 1]) {
4515 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4516 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004520 free(newsrv->conn_src.iface_name);
4521 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4522 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 global.last_checks |= LSTCHK_NETADM;
4524#else
4525 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4526 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004529#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004530 cur_arg += 2;
4531 continue;
4532 }
4533 /* this keyword in not an option of "source" */
4534 break;
4535 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004537 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004538 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4539 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004544 static int srv_dumped;
4545 struct srv_kw *kw;
4546 char *err;
4547
4548 kw = srv_find_kw(args[cur_arg]);
4549 if (kw) {
4550 char *err = NULL;
4551 int code;
4552
4553 if (!kw->parse) {
4554 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4555 file, linenum, args[0], args[1], args[cur_arg]);
4556 cur_arg += 1 + kw->skip ;
4557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
4559 }
4560
4561 if (defsrv && !kw->default_ok) {
4562 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4563 file, linenum, args[0], args[1], args[cur_arg]);
4564 cur_arg += 1 + kw->skip ;
4565 err_code |= ERR_ALERT;
4566 continue;
4567 }
4568
4569 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4570 err_code |= code;
4571
4572 if (code) {
4573 if (err && *err) {
4574 indent_msg(&err, 2);
4575 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4576 }
4577 else
4578 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4579 file, linenum, args[0], args[1], args[cur_arg]);
4580 if (code & ERR_FATAL) {
4581 free(err);
4582 cur_arg += 1 + kw->skip;
4583 goto out;
4584 }
4585 }
4586 free(err);
4587 cur_arg += 1 + kw->skip;
4588 continue;
4589 }
4590
4591 err = NULL;
4592 if (!srv_dumped) {
4593 srv_dump_kws(&err);
4594 indent_msg(&err, 4);
4595 srv_dumped = 1;
4596 }
4597
4598 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4599 file, linenum, args[0], args[1], args[cur_arg],
4600 err ? " Registered keywords :" : "", err ? err : "");
4601 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004602
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
4606 }
4607
4608 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004609 if (newsrv->trackit) {
4610 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4611 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004614 }
4615
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004616 /* If neither a port nor an addr was specified and no check transport
4617 * layer is forced, then the transport layer used by the checks is the
4618 * same as for the production traffic. Otherwise we use raw_sock by
4619 * default, unless one is specified.
4620 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004621 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004622#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004623 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004624#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004625 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4626 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004627 /* try to get the port from check.addr if check.port not set */
4628 if (!newsrv->check.port)
4629 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004630
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004631 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4632 newsrv->check.port = realport; /* by default */
4633 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004634 /* not yet valid, because no port was set on
4635 * the server either. We'll check if we have
4636 * a known port on the first listener.
4637 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004638 struct listener *l;
4639
4640 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004641 newsrv->check.port = get_host_port(&l->addr);
4642 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004643 break;
4644 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004645 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004646 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4648 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004652
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004653 /* Allocate buffer for check requests... */
4654 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004655 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4656 err_code |= ERR_ALERT | ERR_ABORT;
4657 goto out;
4658 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004659 newsrv->check.bi->size = global.tune.chksize;
4660
4661 /* Allocate buffer for check responses... */
4662 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4663 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4664 err_code |= ERR_ALERT | ERR_ABORT;
4665 goto out;
4666 }
4667 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004668
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004669 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004670 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004671 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4672 err_code |= ERR_ALERT | ERR_ABORT;
4673 goto out;
4674 }
4675
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004676 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4677 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 newsrv->state |= SRV_CHECKED;
4679 }
4680
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004681 if (!defsrv) {
4682 if (newsrv->state & SRV_BACKUP)
4683 curproxy->srv_bck++;
4684 else
4685 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004686
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004687 newsrv->prev_state = newsrv->state;
4688 }
William Lallemanda73203e2012-03-12 12:48:57 +01004689 }
4690
4691 else if (strcmp(args[0], "unique-id-format") == 0) {
4692 if (!*(args[1])) {
4693 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696 }
William Lallemand3203ff42012-11-11 17:30:56 +01004697 if (*(args[2])) {
4698 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004702 free(curproxy->uniqueid_format_string);
4703 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004704 }
William Lallemanda73203e2012-03-12 12:48:57 +01004705
4706 else if (strcmp(args[0], "unique-id-header") == 0) {
4707 if (!*(args[1])) {
4708 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
4711 }
4712 free(curproxy->header_unique_id);
4713 curproxy->header_unique_id = strdup(args[1]);
4714 }
4715
William Lallemand723b73a2012-02-08 16:37:49 +01004716 else if (strcmp(args[0], "log-format") == 0) {
4717 if (!*(args[1])) {
4718 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
4721 }
William Lallemand3203ff42012-11-11 17:30:56 +01004722 if (*(args[2])) {
4723 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004727
4728 if (curproxy->logformat_string != default_http_log_format &&
4729 curproxy->logformat_string != default_tcp_log_format &&
4730 curproxy->logformat_string != clf_http_log_format)
4731 free(curproxy->logformat_string);
4732 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
William Lallemand723b73a2012-02-08 16:37:49 +01004734
William Lallemand0f99e342011-10-12 17:50:54 +02004735 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4736 /* delete previous herited or defined syslog servers */
4737 struct logsrv *back;
4738
4739 if (*(args[1]) != 0) {
4740 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
4743 }
4744
William Lallemand723b73a2012-02-08 16:37:49 +01004745 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4746 LIST_DEL(&tmplogsrv->list);
4747 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004748 }
4749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004751 struct logsrv *logsrv;
4752
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004754 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004755 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004756 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004757 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004758 LIST_INIT(&node->list);
4759 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
4762 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004763
4764 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765
William Lallemand0f99e342011-10-12 17:50:54 +02004766 logsrv->facility = get_log_facility(args[2]);
4767 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
4771
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
4773
William Lallemand0f99e342011-10-12 17:50:54 +02004774 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004776 logsrv->level = get_log_level(args[3]);
4777 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 }
4783 }
4784
William Lallemand0f99e342011-10-12 17:50:54 +02004785 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004786 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004787 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004788 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004789 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004793 }
4794 }
4795
Robert Tsai81ae1952007-12-05 10:47:29 +01004796 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004797 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004798 if (!sk) {
4799 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004800 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
William Lallemand0f99e342011-10-12 17:50:54 +02004804 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004805 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004806 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004807 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004808 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
William Lallemand0f99e342011-10-12 17:50:54 +02004812 logsrv->addr = *sk;
4813 if (!get_host_port(&logsrv->addr))
4814 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 }
William Lallemand0f99e342011-10-12 17:50:54 +02004816
4817 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 }
4819 else {
4820 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4821 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
4825 }
4826 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004827 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004828 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004829
Willy Tarreau977b8e42006-12-29 14:19:17 +01004830 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004832
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4835 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004839
4840 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004841 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4842 free(curproxy->conn_src.iface_name);
4843 curproxy->conn_src.iface_name = NULL;
4844 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004845
Willy Tarreaud5191e72010-02-09 20:50:45 +01004846 sk = str2sa(args[1]);
4847 if (!sk) {
4848 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004852 curproxy->conn_src.source_addr = *sk;
4853 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004854
4855 cur_arg = 2;
4856 while (*(args[cur_arg])) {
4857 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004858#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4859#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004860 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004861 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4862 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004865 }
4866#endif
4867 if (!*args[cur_arg + 1]) {
4868 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4869 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004872 }
4873
4874 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004875 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4876 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004877 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004878 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4879 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004880 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4881 char *name, *end;
4882
4883 name = args[cur_arg+1] + 7;
4884 while (isspace(*name))
4885 name++;
4886
4887 end = name;
4888 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4889 end++;
4890
Willy Tarreauef9a3602012-12-08 22:29:20 +01004891 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4892 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4893 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4894 curproxy->conn_src.bind_hdr_len = end - name;
4895 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4896 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4897 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004898
4899 /* now look for an occurrence number */
4900 while (isspace(*end))
4901 end++;
4902 if (*end == ',') {
4903 end++;
4904 name = end;
4905 if (*end == '-')
4906 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004907 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004908 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004909 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004910 }
4911
Willy Tarreauef9a3602012-12-08 22:29:20 +01004912 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004913 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4914 " occurrences values smaller than %d.\n",
4915 file, linenum, MAX_HDR_HISTORY);
4916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
4918 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004919 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004920 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004921 if (!sk) {
4922 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004926 curproxy->conn_src.tproxy_addr = *sk;
4927 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004928 }
4929 global.last_checks |= LSTCHK_NETADM;
4930#if !defined(CONFIG_HAP_LINUX_TPROXY)
4931 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004932#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004933#else /* no TPROXY support */
4934 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004935 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004936 err_code |= ERR_ALERT | ERR_FATAL;
4937 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004938#endif
4939 cur_arg += 2;
4940 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004941 }
4942
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004943 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4944#ifdef SO_BINDTODEVICE
4945 if (!*args[cur_arg + 1]) {
4946 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004950 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004951 free(curproxy->conn_src.iface_name);
4952 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
4953 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004954 global.last_checks |= LSTCHK_NETADM;
4955#else
4956 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4957 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004960#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004961 cur_arg += 2;
4962 continue;
4963 }
4964 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004965 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004970 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4971 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4972 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4979 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983
4984 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004985 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004986 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
4990 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004992 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004993 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
4997 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004999 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005000 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005006 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005007 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
5011 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005013 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005014 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005018 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005020 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005021 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005023 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005024 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005025 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005031 }
5032 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5042 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046
5047 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005048 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005049 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 }
5053 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005055 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005056 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
5060 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005062 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005063 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005069 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005070 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 }
5074 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005076 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005077 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005081 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005083 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005084 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005086 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005089 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005090
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 if (curproxy == &defproxy) {
5092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005096 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005097 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 if (*(args[1]) == 0) {
5100 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005104
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005105 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005106 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5107 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5108 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
5111 }
5112 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5113 }
5114 else if (*args[2]) {
5115 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5116 file, linenum, args[0], args[2]);
5117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
5119 }
5120
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005121 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005122 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005123 wl->s = strdup(args[1]);
5124 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005125 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005134
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_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005137 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete response header from a 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_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 }
5148 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a 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_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 Tarreaubaaee002006-06-26 02:48:02 +02005154 }
5155 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162
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_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +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 Tarreaubaaee002006-06-26 02:48:02 +02005168 }
5169 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005171 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005172 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
5176 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005178 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005179 args[0], args[1], NULL, (const char **)args+2);
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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005184 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005185
Willy Tarreaubaaee002006-06-26 02:48:02 +02005186 if (curproxy == &defproxy) {
5187 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005191 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 if (*(args[1]) == 0) {
5195 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
5199
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005200 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005201 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5202 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5203 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207 err_code |= warnif_cond_requires_req(cond, file, linenum);
5208 }
5209 else if (*args[2]) {
5210 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5211 file, linenum, args[0], args[2]);
5212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005216 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005217 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005218 wl->s = strdup(args[1]);
5219 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
5221 else if (!strcmp(args[0], "errorloc") ||
5222 !strcmp(args[0], "errorloc302") ||
5223 !strcmp(args[0], "errorloc303")) { /* error location */
5224 int errnum, errlen;
5225 char *err;
5226
Willy Tarreau977b8e42006-12-29 14:19:17 +01005227 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005229
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005231 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
5235
5236 errnum = atol(args[1]);
5237 if (!strcmp(args[0], "errorloc303")) {
5238 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5239 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5240 } else {
5241 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5242 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5243 }
5244
Willy Tarreau0f772532006-12-23 20:51:41 +01005245 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5246 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005247 chunk_destroy(&curproxy->errmsg[rc]);
5248 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005249 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005252
5253 if (rc >= HTTP_ERR_SIZE) {
5254 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5255 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 free(err);
5257 }
5258 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005259 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5260 int errnum, errlen, fd;
5261 char *err;
5262 struct stat stat;
5263
5264 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005265 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005266
5267 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005268 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005271 }
5272
5273 fd = open(args[2], O_RDONLY);
5274 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5275 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5276 file, linenum, args[2], args[1]);
5277 if (fd >= 0)
5278 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005281 }
5282
Willy Tarreau27a674e2009-08-17 07:23:33 +02005283 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005284 errlen = stat.st_size;
5285 } else {
5286 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005287 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005288 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005289 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005290 }
5291
5292 err = malloc(errlen); /* malloc() must succeed during parsing */
5293 errnum = read(fd, err, errlen);
5294 if (errnum != errlen) {
5295 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5296 file, linenum, args[2], args[1]);
5297 close(fd);
5298 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005301 }
5302 close(fd);
5303
5304 errnum = atol(args[1]);
5305 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5306 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005307 chunk_destroy(&curproxy->errmsg[rc]);
5308 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005309 break;
5310 }
5311 }
5312
5313 if (rc >= HTTP_ERR_SIZE) {
5314 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5315 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005317 free(err);
5318 }
5319 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005320 else if (!strcmp(args[0], "compression")) {
5321 struct comp *comp;
5322 if (curproxy->comp == NULL) {
5323 comp = calloc(1, sizeof(struct comp));
5324 curproxy->comp = comp;
5325 } else {
5326 comp = curproxy->comp;
5327 }
5328
5329 if (!strcmp(args[1], "algo")) {
5330 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005331 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005332
William Lallemand82fe75c2012-10-23 10:25:10 +02005333 cur_arg = 2;
5334 if (!*args[cur_arg]) {
5335 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5336 file, linenum, args[0]);
5337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
5339 }
5340 while (*(args[cur_arg])) {
5341 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5342 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5343 file, linenum, args[0], args[cur_arg]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
William Lallemand552df672012-11-07 13:21:47 +01005347 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5348 curproxy->comp->algos->end(&ctx);
5349 } else {
5350 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5351 file, linenum, args[0], args[cur_arg]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005355 cur_arg ++;
5356 continue;
5357 }
5358 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005359 else if (!strcmp(args[1], "offload")) {
5360 comp->offload = 1;
5361 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005362 else if (!strcmp(args[1], "type")) {
5363 int cur_arg;
5364 cur_arg = 2;
5365 if (!*args[cur_arg]) {
5366 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5367 file, linenum, args[0]);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371 while (*(args[cur_arg])) {
5372 comp_append_type(comp, args[cur_arg]);
5373 cur_arg ++;
5374 continue;
5375 }
5376 }
5377 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005378 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005379 file, linenum, args[0]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005384 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005385 struct cfg_kw_list *kwl;
5386 int index;
5387
5388 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5389 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5390 if (kwl->kw[index].section != CFG_LISTEN)
5391 continue;
5392 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5393 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005394 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005395 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005396 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005399 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005400 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005401 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005402 err_code |= ERR_WARN;
5403 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005404 }
Willy Tarreau93893792009-07-23 13:19:11 +02005405 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005406 }
5407 }
5408 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005409
Willy Tarreau6daf3432008-01-22 16:44:08 +01005410 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
Willy Tarreau93893792009-07-23 13:19:11 +02005414 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005415 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005416 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417}
5418
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005419int
5420cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5421{
5422
5423 int err_code = 0;
5424 const char *err;
5425
5426 if (!strcmp(args[0], "userlist")) { /* new userlist */
5427 struct userlist *newul;
5428
5429 if (!*args[1]) {
5430 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5431 file, linenum, args[0]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435
5436 err = invalid_char(args[1]);
5437 if (err) {
5438 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5439 file, linenum, *err, args[0], args[1]);
5440 err_code |= ERR_ALERT | ERR_FATAL;
5441 goto out;
5442 }
5443
5444 for (newul = userlist; newul; newul = newul->next)
5445 if (!strcmp(newul->name, args[1])) {
5446 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5447 file, linenum, args[1]);
5448 err_code |= ERR_WARN;
5449 goto out;
5450 }
5451
5452 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5453 if (!newul) {
5454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5455 err_code |= ERR_ALERT | ERR_ABORT;
5456 goto out;
5457 }
5458
5459 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5460 newul->name = strdup(args[1]);
5461
5462 if (!newul->groupusers | !newul->name) {
5463 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5464 err_code |= ERR_ALERT | ERR_ABORT;
5465 goto out;
5466 }
5467
5468 newul->next = userlist;
5469 userlist = newul;
5470
5471 } else if (!strcmp(args[0], "group")) { /* new group */
5472 int cur_arg, i;
5473 const char *err;
5474
5475 if (!*args[1]) {
5476 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5477 file, linenum, args[0]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481
5482 err = invalid_char(args[1]);
5483 if (err) {
5484 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5485 file, linenum, *err, args[0], args[1]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
5489
5490 for(i = 0; i < userlist->grpcnt; i++)
5491 if (!strcmp(userlist->groups[i], args[1])) {
5492 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5493 file, linenum, args[1], userlist->name);
5494 err_code |= ERR_ALERT;
5495 goto out;
5496 }
5497
5498 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5499 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5500 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
5503 }
5504
5505 cur_arg = 2;
5506
5507 while (*args[cur_arg]) {
5508 if (!strcmp(args[cur_arg], "users")) {
5509 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5510 cur_arg += 2;
5511 continue;
5512 } else {
5513 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5514 file, linenum, args[0]);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518 }
5519
5520 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5521 } else if (!strcmp(args[0], "user")) { /* new user */
5522 struct auth_users *newuser;
5523 int cur_arg;
5524
5525 if (!*args[1]) {
5526 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5527 file, linenum, args[0]);
5528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
5530 }
5531
5532 for (newuser = userlist->users; newuser; newuser = newuser->next)
5533 if (!strcmp(newuser->user, args[1])) {
5534 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5535 file, linenum, args[1], userlist->name);
5536 err_code |= ERR_ALERT;
5537 goto out;
5538 }
5539
5540 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5541 if (!newuser) {
5542 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5543 err_code |= ERR_ALERT | ERR_ABORT;
5544 goto out;
5545 }
5546
5547 newuser->user = strdup(args[1]);
5548
5549 newuser->next = userlist->users;
5550 userlist->users = newuser;
5551
5552 cur_arg = 2;
5553
5554 while (*args[cur_arg]) {
5555 if (!strcmp(args[cur_arg], "password")) {
5556#ifndef CONFIG_HAP_CRYPT
5557 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5558 file, linenum);
5559 err_code |= ERR_ALERT;
5560#endif
5561 newuser->pass = strdup(args[cur_arg + 1]);
5562 cur_arg += 2;
5563 continue;
5564 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5565 newuser->pass = strdup(args[cur_arg + 1]);
5566 newuser->flags |= AU_O_INSECURE;
5567 cur_arg += 2;
5568 continue;
5569 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005570 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005571 cur_arg += 2;
5572 continue;
5573 } else {
5574 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5575 file, linenum, args[0]);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
5579 }
5580 } else {
5581 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5582 err_code |= ERR_ALERT | ERR_FATAL;
5583 }
5584
5585out:
5586 return err_code;
5587}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588
5589/*
5590 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005591 * Returns the error code, 0 if OK, or any combination of :
5592 * - ERR_ABORT: must abort ASAP
5593 * - ERR_FATAL: we can continue parsing but not start the service
5594 * - ERR_WARN: a warning has been emitted
5595 * - ERR_ALERT: an alert has been emitted
5596 * Only the two first ones can stop processing, the two others are just
5597 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005599int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005601 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 FILE *f;
5603 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005605 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 if ((f=fopen(file,"r")) == NULL)
5608 return -1;
5609
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005610 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005611 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005612 char *end;
5613 char *args[MAX_LINE_ARGS + 1];
5614 char *line = thisline;
5615
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 linenum++;
5617
5618 end = line + strlen(line);
5619
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005620 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5621 /* Check if we reached the limit and the last char is not \n.
5622 * Watch out for the last line without the terminating '\n'!
5623 */
5624 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005625 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005627 }
5628
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005630 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 line++;
5632
5633 arg = 0;
5634 args[arg] = line;
5635
5636 while (*line && arg < MAX_LINE_ARGS) {
5637 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5638 * C equivalent value. Other combinations left unchanged (eg: \1).
5639 */
5640 if (*line == '\\') {
5641 int skip = 0;
5642 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5643 *line = line[1];
5644 skip = 1;
5645 }
5646 else if (line[1] == 'r') {
5647 *line = '\r';
5648 skip = 1;
5649 }
5650 else if (line[1] == 'n') {
5651 *line = '\n';
5652 skip = 1;
5653 }
5654 else if (line[1] == 't') {
5655 *line = '\t';
5656 skip = 1;
5657 }
5658 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005659 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660 unsigned char hex1, hex2;
5661 hex1 = toupper(line[2]) - '0';
5662 hex2 = toupper(line[3]) - '0';
5663 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5664 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5665 *line = (hex1<<4) + hex2;
5666 skip = 3;
5667 }
5668 else {
5669 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 }
5672 }
5673 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005674 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 end -= skip;
5676 }
5677 line++;
5678 }
5679 else if (*line == '#' || *line == '\n' || *line == '\r') {
5680 /* end of string, end of loop */
5681 *line = 0;
5682 break;
5683 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005684 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005686 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005687 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 line++;
5689 args[++arg] = line;
5690 }
5691 else {
5692 line++;
5693 }
5694 }
5695
5696 /* empty line */
5697 if (!**args)
5698 continue;
5699
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005700 if (*line) {
5701 /* we had to stop due to too many args.
5702 * Let's terminate the string, print the offending part then cut the
5703 * last arg.
5704 */
5705 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5706 line++;
5707 *line = '\0';
5708
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005709 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005710 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 args[arg] = line;
5713 }
5714
Willy Tarreau540abe42007-05-02 20:50:16 +02005715 /* zero out remaining args and ensure that at least one entry
5716 * is zeroed out.
5717 */
5718 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 args[arg] = line;
5720 }
5721
Willy Tarreau3842f002009-06-14 11:39:52 +02005722 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005723 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005724 char *tmp;
5725
Willy Tarreau3842f002009-06-14 11:39:52 +02005726 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005727 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005728 for (arg=0; *args[arg+1]; arg++)
5729 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005730 *tmp = '\0'; // fix the next arg to \0
5731 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005732 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005733 else if (!strcmp(args[0], "default")) {
5734 kwm = KWM_DEF;
5735 for (arg=0; *args[arg+1]; arg++)
5736 args[arg] = args[arg+1]; // shift args after inversion
5737 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005738
William Lallemand0f99e342011-10-12 17:50:54 +02005739 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5740 strcmp(args[0], "log") != 0) {
5741 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005742 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005743 }
5744
Willy Tarreau977b8e42006-12-29 14:19:17 +01005745 if (!strcmp(args[0], "listen") ||
5746 !strcmp(args[0], "frontend") ||
5747 !strcmp(args[0], "backend") ||
5748 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005749 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005751 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005752 cursection = strdup(args[0]);
5753 }
5754 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005756 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005757 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005758 }
5759 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005760 confsect = CFG_USERLIST;
5761 free(cursection);
5762 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005763 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005764 else if (!strcmp(args[0], "peers")) {
5765 confsect = CFG_PEERS;
5766 free(cursection);
5767 cursection = strdup(args[0]);
5768 }
5769
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 /* else it's a section keyword */
5771
5772 switch (confsect) {
5773 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 break;
5776 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005777 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005779 case CFG_USERLIST:
5780 err_code |= cfg_parse_users(file, linenum, args, kwm);
5781 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005782 case CFG_PEERS:
5783 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5784 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005786 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005787 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005789
5790 if (err_code & ERR_ABORT)
5791 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005793 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005794 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005796 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005797}
5798
Willy Tarreaubb925012009-07-23 13:36:36 +02005799/*
5800 * Returns the error code, 0 if OK, or any combination of :
5801 * - ERR_ABORT: must abort ASAP
5802 * - ERR_FATAL: we can continue parsing but not start the service
5803 * - ERR_WARN: a warning has been emitted
5804 * - ERR_ALERT: an alert has been emitted
5805 * Only the two first ones can stop processing, the two others are just
5806 * indicators.
5807 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005808int check_config_validity()
5809{
5810 int cfgerr = 0;
5811 struct proxy *curproxy = NULL;
5812 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005813 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005814 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005815 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005816 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005818 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 /*
5820 * Now, check for the integrity of all that we have collected.
5821 */
5822
5823 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005824 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825
Willy Tarreau193b8c62012-11-22 00:17:38 +01005826 if (!global.tune.max_http_hdr)
5827 global.tune.max_http_hdr = MAX_HTTP_HDR;
5828
5829 if (!global.tune.cookie_len)
5830 global.tune.cookie_len = CAPTURE_LEN;
5831
5832 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5833
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005834 /* first, we will invert the proxy list order */
5835 curproxy = NULL;
5836 while (proxy) {
5837 struct proxy *next;
5838
5839 next = proxy->next;
5840 proxy->next = curproxy;
5841 curproxy = proxy;
5842 if (!next)
5843 break;
5844 proxy = next;
5845 }
5846
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005848 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005849 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005850 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005851 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005852 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005853 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005854 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005855
Willy Tarreau050536d2012-10-04 08:47:34 +02005856 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005857 /* proxy ID not set, use automatic numbering with first
5858 * spare entry starting with next_pxid.
5859 */
5860 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5861 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5862 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005863 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005864 next_pxid++;
5865
Willy Tarreau55ea7572007-06-17 19:56:27 +02005866
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005868 /* ensure we don't keep listeners uselessly bound */
5869 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 curproxy = curproxy->next;
5871 continue;
5872 }
5873
Willy Tarreau16a21472012-11-19 12:39:59 +01005874 /* number of processes this proxy is bound to */
5875 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5876
Willy Tarreauff01a212009-03-15 13:46:16 +01005877 switch (curproxy->mode) {
5878 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005880 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005881 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5882 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005883 cfgerr++;
5884 }
5885
5886 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005887 Warning("config : servers will be ignored for %s '%s'.\n",
5888 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005889 break;
5890
5891 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005892 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005893 break;
5894
5895 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005896 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005897 break;
5898 }
5899
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005900 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005901 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005902 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005903 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5904 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005905 cfgerr++;
5906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005908 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005909 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5910 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005911 cfgerr++;
5912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005914 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005915 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5916 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005917 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005918 }
5919 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005920 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005921 /* If no LB algo is set in a backend, and we're not in
5922 * transparent mode, dispatch mode nor proxy mode, we
5923 * want to use balance roundrobin by default.
5924 */
5925 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5926 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005927 }
5928 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005929
Willy Tarreau1620ec32011-08-06 17:05:02 +02005930 if (curproxy->options & PR_O_DISPATCH)
5931 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5932 else if (curproxy->options & PR_O_HTTP_PROXY)
5933 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5934 else if (curproxy->options & PR_O_TRANSP)
5935 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005936
Willy Tarreau1620ec32011-08-06 17:05:02 +02005937 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5938 if (curproxy->options & PR_O_DISABLE404) {
5939 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5940 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5941 err_code |= ERR_WARN;
5942 curproxy->options &= ~PR_O_DISABLE404;
5943 }
5944 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5945 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5946 "send-state", proxy_type_str(curproxy), curproxy->id);
5947 err_code |= ERR_WARN;
5948 curproxy->options &= ~PR_O2_CHK_SNDST;
5949 }
Willy Tarreauef781042010-01-27 11:53:01 +01005950 }
5951
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005952 /* if a default backend was specified, let's find it */
5953 if (curproxy->defbe.name) {
5954 struct proxy *target;
5955
Alex Williams96532db2009-11-01 21:27:13 -05005956 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005957 if (!target) {
5958 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5959 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005960 cfgerr++;
5961 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005962 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5963 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005964 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005965 } else {
5966 free(curproxy->defbe.name);
5967 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005968 /* we force the backend to be present on at least all of
5969 * the frontend's processes.
5970 */
5971 target->bind_proc = curproxy->bind_proc ?
5972 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005973
5974 /* Emit a warning if this proxy also has some servers */
5975 if (curproxy->srv) {
5976 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5977 curproxy->id);
5978 err_code |= ERR_WARN;
5979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
5981 }
5982
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005983 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005984 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5985 /* map jump target for ACT_SETBE in req_rep chain */
5986 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005987 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005988 struct proxy *target;
5989
Willy Tarreaua496b602006-12-17 23:15:24 +01005990 if (exp->action != ACT_SETBE)
5991 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005992
Alex Williams96532db2009-11-01 21:27:13 -05005993 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005994 if (!target) {
5995 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5996 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005997 cfgerr++;
5998 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005999 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6000 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006001 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006002 } else {
6003 free((void *)exp->replace);
6004 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006005 /* we force the backend to be present on at least all of
6006 * the frontend's processes.
6007 */
6008 target->bind_proc = curproxy->bind_proc ?
6009 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006010 }
6011 }
6012 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006013
6014 /* find the target proxy for 'use_backend' rules */
6015 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006016 struct proxy *target;
6017
Alex Williams96532db2009-11-01 21:27:13 -05006018 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006019
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006020 if (!target) {
6021 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6022 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006023 cfgerr++;
6024 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006025 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6026 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006027 cfgerr++;
6028 } else {
6029 free((void *)rule->be.name);
6030 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006031 /* we force the backend to be present on at least all of
6032 * the frontend's processes.
6033 */
6034 target->bind_proc = curproxy->bind_proc ?
6035 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006036 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006037 }
6038
6039 /* find the target proxy for 'use_backend' rules */
6040 list_for_each_entry(srule, &curproxy->server_rules, list) {
6041 struct server *target = findserver(curproxy, srule->srv.name);
6042
6043 if (!target) {
6044 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6045 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6046 cfgerr++;
6047 continue;
6048 }
6049 free((void *)srule->srv.name);
6050 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006051 }
6052
Emeric Brunb982a3d2010-01-04 15:45:53 +01006053 /* find the target table for 'stick' rules */
6054 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6055 struct proxy *target;
6056
Emeric Brun1d33b292010-01-04 15:47:17 +01006057 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6058 if (mrule->flags & STK_IS_STORE)
6059 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6060
Emeric Brunb982a3d2010-01-04 15:45:53 +01006061 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006062 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006063 else
6064 target = curproxy;
6065
6066 if (!target) {
6067 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6068 curproxy->id, mrule->table.name);
6069 cfgerr++;
6070 }
6071 else if (target->table.size == 0) {
6072 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6073 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6074 cfgerr++;
6075 }
Willy Tarreau12785782012-04-27 21:37:17 +02006076 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6077 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006078 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6079 cfgerr++;
6080 }
6081 else {
6082 free((void *)mrule->table.name);
6083 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006084 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006085 }
6086 }
6087
6088 /* find the target table for 'store response' rules */
6089 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6090 struct proxy *target;
6091
Emeric Brun1d33b292010-01-04 15:47:17 +01006092 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6093
Emeric Brunb982a3d2010-01-04 15:45:53 +01006094 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006095 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006096 else
6097 target = curproxy;
6098
6099 if (!target) {
6100 Alert("Proxy '%s': unable to find store table '%s'.\n",
6101 curproxy->id, mrule->table.name);
6102 cfgerr++;
6103 }
6104 else if (target->table.size == 0) {
6105 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6106 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6107 cfgerr++;
6108 }
Willy Tarreau12785782012-04-27 21:37:17 +02006109 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6110 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006111 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6112 cfgerr++;
6113 }
6114 else {
6115 free((void *)mrule->table.name);
6116 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006117 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006118 }
6119 }
6120
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006121 /* find the target table for 'tcp-request' layer 4 rules */
6122 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6123 struct proxy *target;
6124
Willy Tarreau56123282010-08-06 19:06:56 +02006125 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006126 continue;
6127
6128 if (trule->act_prm.trk_ctr.table.n)
6129 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6130 else
6131 target = curproxy;
6132
6133 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006134 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6135 curproxy->id, trule->act_prm.trk_ctr.table.n,
6136 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006137 cfgerr++;
6138 }
6139 else if (target->table.size == 0) {
6140 Alert("Proxy '%s': table '%s' used but not configured.\n",
6141 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6142 cfgerr++;
6143 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006144 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6145 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6146 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6147 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6148 cfgerr++;
6149 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006150 else {
6151 free(trule->act_prm.trk_ctr.table.n);
6152 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006153 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006154 * to pass a list of counters to track and allocate them right here using
6155 * stktable_alloc_data_type().
6156 */
6157 }
6158 }
6159
Willy Tarreaud1f96522010-08-03 19:34:32 +02006160 /* find the target table for 'tcp-request' layer 6 rules */
6161 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6162 struct proxy *target;
6163
Willy Tarreau56123282010-08-06 19:06:56 +02006164 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006165 continue;
6166
6167 if (trule->act_prm.trk_ctr.table.n)
6168 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6169 else
6170 target = curproxy;
6171
6172 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006173 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6174 curproxy->id, trule->act_prm.trk_ctr.table.n,
6175 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006176 cfgerr++;
6177 }
6178 else if (target->table.size == 0) {
6179 Alert("Proxy '%s': table '%s' used but not configured.\n",
6180 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6181 cfgerr++;
6182 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006183 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6184 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6185 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6186 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6187 cfgerr++;
6188 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006189 else {
6190 free(trule->act_prm.trk_ctr.table.n);
6191 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006192 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006193 * to pass a list of counters to track and allocate them right here using
6194 * stktable_alloc_data_type().
6195 */
6196 }
6197 }
6198
Emeric Brun32da3c42010-09-23 18:39:19 +02006199 if (curproxy->table.peers.name) {
6200 struct peers *curpeers = peers;
6201
6202 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6203 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6204 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006205 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006206 break;
6207 }
6208 }
6209
6210 if (!curpeers) {
6211 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6212 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006213 free((void *)curproxy->table.peers.name);
6214 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006215 cfgerr++;
6216 }
6217 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006218 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6219 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006220 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006221 cfgerr++;
6222 }
6223 }
6224
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006225 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006226 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006227 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6228 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6229 "proxy", curproxy->id);
6230 cfgerr++;
6231 goto out_uri_auth_compat;
6232 }
6233
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006234 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006235 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006236 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006237 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006238
Willy Tarreau95fa4692010-02-01 13:05:50 +01006239 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6240 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006241
6242 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006243 uri_auth_compat_req[i++] = "realm";
6244 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6245 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006246
Willy Tarreau95fa4692010-02-01 13:05:50 +01006247 uri_auth_compat_req[i++] = "unless";
6248 uri_auth_compat_req[i++] = "{";
6249 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6250 uri_auth_compat_req[i++] = "}";
6251 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006252
Willy Tarreauff011f22011-01-06 17:51:27 +01006253 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6254 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006255 cfgerr++;
6256 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006257 }
6258
Willy Tarreauff011f22011-01-06 17:51:27 +01006259 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006260
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006261 if (curproxy->uri_auth->auth_realm) {
6262 free(curproxy->uri_auth->auth_realm);
6263 curproxy->uri_auth->auth_realm = NULL;
6264 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006265
6266 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006267 }
6268out_uri_auth_compat:
6269
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006270 cfgerr += acl_find_targets(curproxy);
6271
Willy Tarreau2738a142006-07-08 17:28:09 +02006272 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006273 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006274 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006275 (!curproxy->timeout.connect ||
6276 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006277 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006278 " | While not properly invalid, you will certainly encounter various problems\n"
6279 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006280 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006281 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006282 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006283 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006284
Willy Tarreau1fa31262007-12-03 00:36:16 +01006285 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6286 * We must still support older configurations, so let's find out whether those
6287 * parameters have been set or must be copied from contimeouts.
6288 */
6289 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006290 if (!curproxy->timeout.tarpit ||
6291 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006292 /* tarpit timeout not set. We search in the following order:
6293 * default.tarpit, curr.connect, default.connect.
6294 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006295 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006296 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006297 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006298 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006299 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006300 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006301 }
6302 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006303 (!curproxy->timeout.queue ||
6304 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006305 /* queue timeout not set. We search in the following order:
6306 * default.queue, curr.connect, default.connect.
6307 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006308 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006309 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006310 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006311 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006312 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006313 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006314 }
6315 }
6316
Willy Tarreau1620ec32011-08-06 17:05:02 +02006317 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006318 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6319 curproxy->check_req = (char *)malloc(curproxy->check_len);
6320 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006321 }
6322
Willy Tarreau193b8c62012-11-22 00:17:38 +01006323 /* ensure that cookie capture length is not too large */
6324 if (curproxy->capture_len >= global.tune.cookie_len) {
6325 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6326 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6327 err_code |= ERR_WARN;
6328 curproxy->capture_len = global.tune.cookie_len - 1;
6329 }
6330
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006331 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006332 if (curproxy->nb_req_cap) {
6333 if (curproxy->mode == PR_MODE_HTTP) {
6334 curproxy->req_cap_pool = create_pool("ptrcap",
6335 curproxy->nb_req_cap * sizeof(char *),
6336 MEM_F_SHARED);
6337 } else {
6338 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6339 proxy_type_str(curproxy), curproxy->id);
6340 err_code |= ERR_WARN;
6341 curproxy->to_log &= ~LW_REQHDR;
6342 curproxy->nb_req_cap = 0;
6343 }
6344 }
6345
6346 if (curproxy->nb_rsp_cap) {
6347 if (curproxy->mode == PR_MODE_HTTP) {
6348 curproxy->rsp_cap_pool = create_pool("ptrcap",
6349 curproxy->nb_rsp_cap * sizeof(char *),
6350 MEM_F_SHARED);
6351 } else {
6352 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6353 proxy_type_str(curproxy), curproxy->id);
6354 err_code |= ERR_WARN;
6355 curproxy->to_log &= ~LW_REQHDR;
6356 curproxy->nb_rsp_cap = 0;
6357 }
6358 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006359
Willy Tarreau196729e2012-05-31 19:30:26 +02006360 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006361 if (!(curproxy->cap & PR_CAP_FE)) {
6362 if (curproxy->logformat_string != default_http_log_format &&
6363 curproxy->logformat_string != default_tcp_log_format &&
6364 curproxy->logformat_string != clf_http_log_format)
6365 free(curproxy->logformat_string);
6366 curproxy->logformat_string = NULL;
6367 }
6368
Willy Tarreau196729e2012-05-31 19:30:26 +02006369 if (curproxy->logformat_string)
6370 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6371
6372 if (curproxy->uniqueid_format_string)
6373 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6374
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 /* first, we will invert the servers list order */
6376 newsrv = NULL;
6377 while (curproxy->srv) {
6378 struct server *next;
6379
6380 next = curproxy->srv->next;
6381 curproxy->srv->next = newsrv;
6382 newsrv = curproxy->srv;
6383 if (!next)
6384 break;
6385 curproxy->srv = next;
6386 }
6387
Willy Tarreaudd701652010-05-25 23:03:02 +02006388 /* assign automatic UIDs to servers which don't have one yet */
6389 next_id = 1;
6390 newsrv = curproxy->srv;
6391 while (newsrv != NULL) {
6392 if (!newsrv->puid) {
6393 /* server ID not set, use automatic numbering with first
6394 * spare entry starting with next_svid.
6395 */
6396 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6397 newsrv->conf.id.key = newsrv->puid = next_id;
6398 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6399 }
6400 next_id++;
6401 newsrv = newsrv->next;
6402 }
6403
Willy Tarreau20697042007-11-15 23:26:18 +01006404 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006405 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406
Willy Tarreau62c3be22012-01-20 13:12:32 +01006407 /*
6408 * If this server supports a maxconn parameter, it needs a dedicated
6409 * tasks to fill the emptied slots when a connection leaves.
6410 * Also, resolve deferred tracking dependency if needed.
6411 */
6412 newsrv = curproxy->srv;
6413 while (newsrv != NULL) {
6414 if (newsrv->minconn > newsrv->maxconn) {
6415 /* Only 'minconn' was specified, or it was higher than or equal
6416 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6417 * this will avoid further useless expensive computations.
6418 */
6419 newsrv->maxconn = newsrv->minconn;
6420 } else if (newsrv->maxconn && !newsrv->minconn) {
6421 /* minconn was not specified, so we set it to maxconn */
6422 newsrv->minconn = newsrv->maxconn;
6423 }
6424
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006425#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006426 if (newsrv->use_ssl || newsrv->check.use_ssl)
6427 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006428#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006429
Willy Tarreau62c3be22012-01-20 13:12:32 +01006430 if (newsrv->trackit) {
6431 struct proxy *px;
6432 struct server *srv;
6433 char *pname, *sname;
6434
6435 pname = newsrv->trackit;
6436 sname = strrchr(pname, '/');
6437
6438 if (sname)
6439 *sname++ = '\0';
6440 else {
6441 sname = pname;
6442 pname = NULL;
6443 }
6444
6445 if (pname) {
6446 px = findproxy(pname, PR_CAP_BE);
6447 if (!px) {
6448 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6449 proxy_type_str(curproxy), curproxy->id,
6450 newsrv->id, pname);
6451 cfgerr++;
6452 goto next_srv;
6453 }
6454 } else
6455 px = curproxy;
6456
6457 srv = findserver(px, sname);
6458 if (!srv) {
6459 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6460 proxy_type_str(curproxy), curproxy->id,
6461 newsrv->id, sname);
6462 cfgerr++;
6463 goto next_srv;
6464 }
6465
6466 if (!(srv->state & SRV_CHECKED)) {
6467 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6468 "tracking as it does not have checks enabled.\n",
6469 proxy_type_str(curproxy), curproxy->id,
6470 newsrv->id, px->id, srv->id);
6471 cfgerr++;
6472 goto next_srv;
6473 }
6474
6475 if (curproxy != px &&
6476 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6477 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6478 "tracking: disable-on-404 option inconsistency.\n",
6479 proxy_type_str(curproxy), curproxy->id,
6480 newsrv->id, px->id, srv->id);
6481 cfgerr++;
6482 goto next_srv;
6483 }
6484
6485 /* if the other server is forced disabled, we have to do the same here */
6486 if (srv->state & SRV_MAINTAIN) {
6487 newsrv->state |= SRV_MAINTAIN;
6488 newsrv->state &= ~SRV_RUNNING;
6489 newsrv->health = 0;
6490 }
6491
6492 newsrv->track = srv;
6493 newsrv->tracknext = srv->tracknext;
6494 srv->tracknext = newsrv;
6495
6496 free(newsrv->trackit);
6497 newsrv->trackit = NULL;
6498 }
6499 next_srv:
6500 newsrv = newsrv->next;
6501 }
6502
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006503 /* We have to initialize the server lookup mechanism depending
6504 * on what LB algorithm was choosen.
6505 */
6506
6507 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6508 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6509 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006510 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6511 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6512 init_server_map(curproxy);
6513 } else {
6514 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6515 fwrr_init_server_groups(curproxy);
6516 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006517 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006518
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006519 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006520 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6521 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6522 fwlc_init_server_tree(curproxy);
6523 } else {
6524 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6525 fas_init_server_tree(curproxy);
6526 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006527 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006528
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006529 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006530 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6531 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6532 chash_init_server_tree(curproxy);
6533 } else {
6534 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6535 init_server_map(curproxy);
6536 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006537 break;
6538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006539
6540 if (curproxy->options & PR_O_LOGASAP)
6541 curproxy->to_log &= ~LW_BYTES;
6542
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006543 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006544 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006545 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6546 proxy_type_str(curproxy), curproxy->id);
6547 err_code |= ERR_WARN;
6548 }
6549
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006550 if (curproxy->mode != PR_MODE_HTTP) {
6551 int optnum;
6552
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006553 if (curproxy->uri_auth) {
6554 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6555 proxy_type_str(curproxy), curproxy->id);
6556 err_code |= ERR_WARN;
6557 curproxy->uri_auth = NULL;
6558 }
6559
Willy Tarreau87cf5142011-08-19 22:57:24 +02006560 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006561 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6562 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6563 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006564 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006565 }
6566
6567 if (curproxy->options & PR_O_ORGTO) {
6568 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6569 "originalto", proxy_type_str(curproxy), curproxy->id);
6570 err_code |= ERR_WARN;
6571 curproxy->options &= ~PR_O_ORGTO;
6572 }
6573
6574 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6575 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6576 (curproxy->cap & cfg_opts[optnum].cap) &&
6577 (curproxy->options & cfg_opts[optnum].val)) {
6578 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6579 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6580 err_code |= ERR_WARN;
6581 curproxy->options &= ~cfg_opts[optnum].val;
6582 }
6583 }
6584
6585 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6586 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6587 (curproxy->cap & cfg_opts2[optnum].cap) &&
6588 (curproxy->options2 & cfg_opts2[optnum].val)) {
6589 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6590 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6591 err_code |= ERR_WARN;
6592 curproxy->options2 &= ~cfg_opts2[optnum].val;
6593 }
6594 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006595
Willy Tarreauefa5f512010-03-30 20:13:29 +02006596#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006597 if (curproxy->conn_src.bind_hdr_occ) {
6598 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006599 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006600 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006601 err_code |= ERR_WARN;
6602 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006603#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006604 }
6605
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006607 * ensure that we're not cross-dressing a TCP server into HTTP.
6608 */
6609 newsrv = curproxy->srv;
6610 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006611 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006612 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006614 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006615 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006616
Willy Tarreau0cec3312011-10-31 13:49:26 +01006617 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6618 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6619 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6620 err_code |= ERR_WARN;
6621 }
6622
Willy Tarreauefa5f512010-03-30 20:13:29 +02006623#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006624 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6625 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006626 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006627 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006628 err_code |= ERR_WARN;
6629 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006630#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006631 newsrv = newsrv->next;
6632 }
6633
Willy Tarreauc1a21672009-08-16 22:37:44 +02006634 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006635 if (!curproxy->accept)
6636 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006637
Willy Tarreauc1a21672009-08-16 22:37:44 +02006638 if (curproxy->tcp_req.inspect_delay ||
6639 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006640 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006641
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006642 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006643 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006644 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006645 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006646
6647 /* both TCP and HTTP must check switching rules */
6648 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6649 }
6650
6651 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006652 if (curproxy->tcp_req.inspect_delay ||
6653 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6654 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6655
Emeric Brun97679e72010-09-23 17:56:44 +02006656 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6657 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6658
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006659 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006660 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006661 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006662 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006663
6664 /* If the backend does requires RDP cookie persistence, we have to
6665 * enable the corresponding analyser.
6666 */
6667 if (curproxy->options2 & PR_O2_RDPC_PRST)
6668 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6669 }
6670
Emeric Brunc52962f2012-11-15 18:28:02 +01006671#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006672 /* Configure SSL for each bind line.
6673 * Note: if configuration fails at some point, the ->ctx member
6674 * remains NULL so that listeners can later detach.
6675 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006676 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006677 if (!bind_conf->is_ssl) {
6678 if (bind_conf->default_ctx) {
6679 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6680 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6681 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006682 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006683 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006684 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006685 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006686 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006687 cfgerr++;
6688 continue;
6689 }
6690
Emeric Brun4b3091e2012-09-24 15:48:52 +02006691 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006692 Alert("Unable to allocate SSL session cache.\n");
6693 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006694 continue;
6695 }
6696
Emeric Brunfc0421f2012-09-07 17:30:07 +02006697 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006698 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006699 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006700#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006701
Willy Tarreaue6b98942007-10-29 01:09:36 +01006702 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006703 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006704 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006705 if (!listener->luid) {
6706 /* listener ID not set, use automatic numbering with first
6707 * spare entry starting with next_luid.
6708 */
6709 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6710 listener->conf.id.key = listener->luid = next_id;
6711 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006712 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006713 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006714
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006715 /* enable separate counters */
6716 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6717 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006718 if (!listener->name)
6719 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006720 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006721
Willy Tarreaue6b98942007-10-29 01:09:36 +01006722 if (curproxy->options & PR_O_TCP_NOLING)
6723 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006724 if (!listener->maxconn)
6725 listener->maxconn = curproxy->maxconn;
6726 if (!listener->backlog)
6727 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006728 if (!listener->maxaccept)
6729 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6730
6731 /* we want to have an optimal behaviour on single process mode to
6732 * maximize the work at once, but in multi-process we want to keep
6733 * some fairness between processes, so we target half of the max
6734 * number of events to be balanced over all the processes the proxy
6735 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6736 * used to disable the limit.
6737 */
6738 if (listener->maxaccept > 0) {
6739 if (nbproc > 1)
6740 listener->maxaccept = (listener->maxaccept + 1) / 2;
6741 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6742 }
6743
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006744 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006745 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006746 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006747 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006748
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006749 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6750 listener->options |= LI_O_TCP_RULES;
6751
Willy Tarreaude3041d2010-05-31 10:56:17 +02006752 if (curproxy->mon_mask.s_addr)
6753 listener->options |= LI_O_CHK_MONNET;
6754
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006755 /* smart accept mode is automatic in HTTP mode */
6756 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006757 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006758 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6759 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006760 }
6761
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006762 /* Release unused SSL configs */
6763 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6764 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006765 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006766#ifdef USE_OPENSSL
6767 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006768 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006769 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006770 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006771 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006772#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006773 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006774
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006775 /* Check multi-process mode compatibility for the current proxy */
6776 if (global.nbproc > 1) {
6777 int nbproc = 0;
6778 if (curproxy->bind_proc) {
6779 int proc;
6780 for (proc = 0; proc < global.nbproc; proc++) {
6781 if (curproxy->bind_proc & (1 << proc)) {
6782 nbproc++;
6783 }
6784 }
6785 } else {
6786 nbproc = global.nbproc;
6787 }
6788 if (curproxy->table.peers.name) {
6789 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6790 curproxy->id);
6791 cfgerr++;
6792 }
6793 if (nbproc > 1) {
6794 if (curproxy->uri_auth) {
6795 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6796 curproxy->id);
6797 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6798 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6799 curproxy->id);
6800 }
6801 }
6802 if (curproxy->appsession_name) {
6803 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6804 curproxy->id);
6805 }
6806 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6807 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6808 curproxy->id);
6809 }
6810 }
6811 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006812
6813 /* create the task associated with the proxy */
6814 curproxy->task = task_new();
6815 if (curproxy->task) {
6816 curproxy->task->context = curproxy;
6817 curproxy->task->process = manage_proxy;
6818 /* no need to queue, it will be done automatically if some
6819 * listener gets limited.
6820 */
6821 curproxy->task->expire = TICK_ETERNITY;
6822 } else {
6823 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6824 curproxy->id);
6825 cfgerr++;
6826 }
6827
Willy Tarreaubaaee002006-06-26 02:48:02 +02006828 curproxy = curproxy->next;
6829 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006830
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006831 /* Check multi-process mode compatibility */
6832 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006833 if (global.stats_fe && !global.stats_fe->bind_proc) {
6834 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 +01006835 }
6836 }
6837
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006838 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6839 struct auth_users *curuser;
6840 int g;
6841
6842 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6843 unsigned int group_mask = 0;
6844 char *group = NULL;
6845
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006846 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006847 continue;
6848
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006849 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006850
6851 for (g = 0; g < curuserlist->grpcnt; g++)
6852 if (!strcmp(curuserlist->groups[g], group))
6853 break;
6854
6855 if (g == curuserlist->grpcnt) {
6856 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6857 curuserlist->name, group, curuser->user);
6858 err_code |= ERR_ALERT | ERR_FATAL;
6859 goto out;
6860 }
6861
6862 group_mask |= (1 << g);
6863 }
6864
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006865 free(curuser->u.groups);
6866 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006867 }
6868
6869 for (g = 0; g < curuserlist->grpcnt; g++) {
6870 char *user = NULL;
6871
6872 if (!curuserlist->groupusers[g])
6873 continue;
6874
6875 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6876 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6877 if (!strcmp(curuser->user, user))
6878 break;
6879
6880 if (!curuser) {
6881 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6882 curuserlist->name, user, curuserlist->groups[g]);
6883 err_code |= ERR_ALERT | ERR_FATAL;
6884 goto out;
6885 }
6886
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006887 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006888 }
6889
6890 free(curuserlist->groupusers[g]);
6891 }
6892
6893 free(curuserlist->groupusers);
6894
6895#ifdef DEBUG_AUTH
6896 for (g = 0; g < curuserlist->grpcnt; g++) {
6897 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6898
6899 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006900 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006901 fprintf(stderr, " %s", curuser->user);
6902 }
6903
6904 fprintf(stderr, "\n");
6905 }
6906#endif
6907
Willy Tarreaufbb78422011-06-05 15:38:35 +02006908 }
6909
6910 /* automatically compute fullconn if not set. We must not do it in the
6911 * loop above because cross-references are not yet fully resolved.
6912 */
6913 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6914 /* If <fullconn> is not set, let's set it to 10% of the sum of
6915 * the possible incoming frontend's maxconns.
6916 */
6917 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6918 struct proxy *fe;
6919 int total = 0;
6920
6921 /* sum up the number of maxconns of frontends which
6922 * reference this backend at least once or which are
6923 * the same one ('listen').
6924 */
6925 for (fe = proxy; fe; fe = fe->next) {
6926 struct switching_rule *rule;
6927 struct hdr_exp *exp;
6928 int found = 0;
6929
6930 if (!(fe->cap & PR_CAP_FE))
6931 continue;
6932
6933 if (fe == curproxy) /* we're on a "listen" instance */
6934 found = 1;
6935
6936 if (fe->defbe.be == curproxy) /* "default_backend" */
6937 found = 1;
6938
6939 /* check if a "use_backend" rule matches */
6940 if (!found) {
6941 list_for_each_entry(rule, &fe->switching_rules, list) {
6942 if (rule->be.backend == curproxy) {
6943 found = 1;
6944 break;
6945 }
6946 }
6947 }
6948
6949 /* check if a "reqsetbe" rule matches */
6950 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6951 if (exp->action == ACT_SETBE &&
6952 (struct proxy *)exp->replace == curproxy) {
6953 found = 1;
6954 break;
6955 }
6956 }
6957
6958 /* now we've checked all possible ways to reference a backend
6959 * from a frontend.
6960 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006961 if (!found)
6962 continue;
6963 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006964 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006965 /* we have the sum of the maxconns in <total>. We only
6966 * keep 10% of that sum to set the default fullconn, with
6967 * a hard minimum of 1 (to avoid a divide by zero).
6968 */
6969 curproxy->fullconn = (total + 9) / 10;
6970 if (!curproxy->fullconn)
6971 curproxy->fullconn = 1;
6972 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006973 }
6974
Willy Tarreau056f5682010-06-06 15:51:11 +02006975 /* initialize stick-tables on backend capable proxies. This must not
6976 * be done earlier because the data size may be discovered while parsing
6977 * other proxies.
6978 */
6979 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006980 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006981
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006982 /*
6983 * Recount currently required checks.
6984 */
6985
6986 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6987 int optnum;
6988
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006989 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6990 if (curproxy->options & cfg_opts[optnum].val)
6991 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006992
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006993 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6994 if (curproxy->options2 & cfg_opts2[optnum].val)
6995 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006996 }
6997
Willy Tarreau122541c2011-09-07 21:24:49 +02006998 if (peers) {
6999 struct peers *curpeers = peers, **last;
7000 struct peer *p, *pb;
7001
7002 /* Remove all peers sections which don't have a valid listener.
7003 * This can happen when a peers section is never referenced and
7004 * does not contain a local peer.
7005 */
7006 last = &peers;
7007 while (*last) {
7008 curpeers = *last;
7009 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007010 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007011 last = &curpeers->next;
7012 continue;
7013 }
7014
7015 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7016 curpeers->id, localpeer);
7017
7018 p = curpeers->remote;
7019 while (p) {
7020 pb = p->next;
7021 free(p->id);
7022 free(p);
7023 p = pb;
7024 }
7025
7026 /* Destroy and unlink this curpeers section.
7027 * Note: curpeers is backed up into *last.
7028 */
7029 free(curpeers->id);
7030 curpeers = curpeers->next;
7031 free(*last);
7032 *last = curpeers;
7033 }
7034 }
7035
Willy Tarreau34eb6712011-10-24 18:15:04 +02007036 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007037 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007038 MEM_F_SHARED);
7039
Willy Tarreaubb925012009-07-23 13:36:36 +02007040 if (cfgerr > 0)
7041 err_code |= ERR_ALERT | ERR_FATAL;
7042 out:
7043 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007044}
7045
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007046/*
7047 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7048 * parsing sessions.
7049 */
7050void cfg_register_keywords(struct cfg_kw_list *kwl)
7051{
7052 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7053}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007054
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007055/*
7056 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7057 */
7058void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7059{
7060 LIST_DEL(&kwl->list);
7061 LIST_INIT(&kwl->list);
7062}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007063
7064/*
7065 * Local variables:
7066 * c-indent-level: 8
7067 * c-basic-offset: 8
7068 * End:
7069 */