blob: c6138fd72bd82bee9b609132ea4ecb945700aa0d [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>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020043#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020045#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020054#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020056#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100114struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 const char *name;
116 unsigned int val;
117 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100118 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100119 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100120};
121
122/* proxy->options */
123static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100124{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100125 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
126 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
127 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
129 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
130 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
131 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
135 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
136 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
137 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
138 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
139 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
140 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100141#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100143#else
144 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100145#endif
146
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148};
149
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150/* proxy->options2 */
151static const struct cfg_opt cfg_opts2[] =
152{
153#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
155 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100157#else
158 { "splice-request", 0, 0, 0, 0 },
159 { "splice-response", 0, 0, 0, 0 },
160 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100161#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
163 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
165 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
166 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
167 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
168 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
170 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400171 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200173 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200174 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100175 { NULL, 0, 0, 0 }
176};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177
Willy Tarreau6daf3432008-01-22 16:44:08 +0100178static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
180int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100181int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200183/* List head of all known configuration keywords */
184static struct cfg_kw_list cfg_keywords = {
185 .list = LIST_HEAD_INIT(cfg_keywords.list)
186};
187
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188/*
189 * converts <str> to a list of listeners which are dynamically allocated.
190 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
191 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
192 * - <port> is a numerical port from 1 to 65535 ;
193 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
194 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200195 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
196 * not NULL, it must be a valid pointer to either NULL or a freeable area that
197 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200199int 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 +0200200{
201 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100202 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 int port, end;
204
205 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 while (next && *next) {
208 struct sockaddr_storage ss;
209
210 str = next;
211 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100212 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 *next++ = 0;
214 }
215
Emeric Bruned760922010-10-22 17:59:25 +0200216 if (*str == '/') {
217 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
218 /* so compute max path */
219 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
220 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 +0200221
Emeric Bruned760922010-10-22 17:59:25 +0200222 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200224 goto fail;
225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200228 ss.ss_family = AF_UNIX;
229 if (global.unix_bind.prefix) {
230 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
231 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 }
Emeric Bruned760922010-10-22 17:59:25 +0200233 else {
234 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
235 }
236 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 }
238 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100241 ss2 = str2sa_range(str, &port, &end);
242 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 /* OK the address looks correct */
253 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Emeric Bruned760922010-10-22 17:59:25 +0200255 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200256 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
265
266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200268 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
269 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
270 l->frontend = curproxy;
271 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
273 l->fd = -1;
274 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200275 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100276 l->state = LI_INIT;
277
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100278 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100280 tcpv4_add_listener(l);
281 }
Emeric Bruned760922010-10-22 17:59:25 +0200282 else if (ss.ss_family == AF_INET6) {
283 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
284 tcpv6_add_listener(l);
285 }
286 else {
Emeric Bruned760922010-10-22 17:59:25 +0200287 uxst_add_listener(l);
288 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200290 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100291 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 } /* end for(port) */
293 } /* end while(next) */
294 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200295 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 fail:
297 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299}
300
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301/*
302 * Sends a warning if proxy <proxy> does not have at least one of the
303 * capabilities in <cap>. An optionnal <hint> may be added at the end
304 * of the warning to help the user. Returns 1 if a warning was emitted
305 * or 0 if the condition is valid.
306 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100307int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100308{
309 char *msg;
310
311 switch (cap) {
312 case PR_CAP_BE: msg = "no backend"; break;
313 case PR_CAP_FE: msg = "no frontend"; break;
314 case PR_CAP_RS: msg = "no ruleset"; break;
315 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
316 default: msg = "not enough"; break;
317 }
318
319 if (!(proxy->cap & cap)) {
320 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100321 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100322 return 1;
323 }
324 return 0;
325}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326
Willy Tarreau61d18892009-03-31 10:49:21 +0200327/* Report a warning if a rule is placed after a 'block' rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100330int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200331{
332 if (!LIST_ISEMPTY(&proxy->block_cond)) {
333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a reqrewrite rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100343int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200344{
345 if (proxy->req_exp) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a reqadd rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100356int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200357{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100358 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* Report a warning if a rule is placed after a redirect rule.
367 * Return 1 if the warning has been emitted, otherwise 0.
368 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
372 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
373 file, line, arg);
374 return 1;
375 }
376 return 0;
377}
378
379/* Report a warning if a rule is placed after a 'use_backend' rule.
380 * Return 1 if the warning has been emitted, otherwise 0.
381 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
385 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
386 file, line, arg);
387 return 1;
388 }
389 return 0;
390}
391
392/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
396 warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
405 warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
409/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
412 return warnif_rule_after_redirect(proxy, file, line, arg) ||
413 warnif_rule_after_use_backend(proxy, file, line, arg);
414}
415
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100416/* Report it if a request ACL condition uses some response-only parameters. It
417 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
418 * Note that <cond> may be NULL and then will be ignored.
419 */
420static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
421{
422 struct acl *acl;
423
424 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
425 return 0;
426
427 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
428 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
429 file, line, acl ? acl->name : "(unknown)");
430 return ERR_WARN;
431}
432
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100433/* Report it if a request ACL condition uses some request-only volatile parameters.
434 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
435 * Note that <cond> may be NULL and then will be ignored.
436 */
437static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
438{
439 struct acl *acl;
440
441 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
442 return 0;
443
444 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
445 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
446 file, line, acl ? acl->name : "(unknown)");
447 return ERR_WARN;
448}
449
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200452 * parse a line in a <global> section. Returns the error code, 0 if OK, or
453 * any combination of :
454 * - ERR_ABORT: must abort ASAP
455 * - ERR_FATAL: we can continue parsing but not start the service
456 * - ERR_WARN: a warning has been emitted
457 * - ERR_ALERT: an alert has been emitted
458 * Only the two first ones can stop processing, the two others are just
459 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200461int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462{
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200464 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465
466 if (!strcmp(args[0], "global")) { /* new section */
467 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200470 else if (!strcmp(args[0], "ca-base")) {
471#ifdef USE_OPENSSL
472 if (global.ca_base != NULL) {
473 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
474 err_code |= ERR_ALERT;
475 goto out;
476 }
477 if (*(args[1]) == 0) {
478 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
479 err_code |= ERR_ALERT | ERR_FATAL;
480 goto out;
481 }
482 global.ca_base = strdup(args[1]);
483#else
484 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
485 err_code |= ERR_ALERT | ERR_FATAL;
486 goto out;
487#endif
488 }
489 else if (!strcmp(args[0], "crt-base")) {
490#ifdef USE_OPENSSL
491 if (global.crt_base != NULL) {
492 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
493 err_code |= ERR_ALERT;
494 goto out;
495 }
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.crt_base = strdup(args[1]);
502#else
503 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
506#endif
507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 else if (!strcmp(args[0], "daemon")) {
509 global.mode |= MODE_DAEMON;
510 }
511 else if (!strcmp(args[0], "debug")) {
512 global.mode |= MODE_DEBUG;
513 }
514 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100515 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200516 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100518 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 }
520 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100521 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100524 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100526 else if (!strcmp(args[0], "nosplice")) {
527 global.tune.options &= ~GTUNE_USE_SPLICE;
528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 else if (!strcmp(args[0], "quiet")) {
530 global.mode |= MODE_QUIET;
531 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 else if (!strcmp(args[0], "tune.maxpollevents")) {
533 if (global.tune.maxpollevents != 0) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200542 }
543 global.tune.maxpollevents = atol(args[1]);
544 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 else if (!strcmp(args[0], "tune.maxaccept")) {
546 if (global.tune.maxaccept != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100555 }
556 global.tune.maxaccept = atol(args[1]);
557 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200558 else if (!strcmp(args[0], "tune.chksize")) {
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.chksize = atol(args[1]);
565 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566#ifdef USE_OPENSSL
567 else if (!strcmp(args[0], "tune.sslcachesize")) {
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
572 }
573 global.tune.sslcachesize = atol(args[1]);
574 }
575#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200576 else if (!strcmp(args[0], "tune.bufsize")) {
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.bufsize = atol(args[1]);
583 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
584 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200585 trashlen = global.tune.bufsize;
586 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200587 }
588 else if (!strcmp(args[0], "tune.maxrewrite")) {
589 if (*(args[1]) == 0) {
590 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT | ERR_FATAL;
592 goto out;
593 }
594 global.tune.maxrewrite = atol(args[1]);
595 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
596 global.tune.maxrewrite = global.tune.bufsize / 2;
597 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100598 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
599 if (global.tune.client_rcvbuf != 0) {
600 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT;
602 goto out;
603 }
604 if (*(args[1]) == 0) {
605 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
606 err_code |= ERR_ALERT | ERR_FATAL;
607 goto out;
608 }
609 global.tune.client_rcvbuf = atol(args[1]);
610 }
611 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
612 if (global.tune.server_rcvbuf != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT;
615 goto out;
616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622 global.tune.server_rcvbuf = atol(args[1]);
623 }
624 else if (!strcmp(args[0], "tune.sndbuf.client")) {
625 if (global.tune.client_sndbuf != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT;
628 goto out;
629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
634 }
635 global.tune.client_sndbuf = atol(args[1]);
636 }
637 else if (!strcmp(args[0], "tune.sndbuf.server")) {
638 if (global.tune.server_sndbuf != 0) {
639 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT;
641 goto out;
642 }
643 if (*(args[1]) == 0) {
644 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT | ERR_FATAL;
646 goto out;
647 }
648 global.tune.server_sndbuf = atol(args[1]);
649 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200650 else if (!strcmp(args[0], "tune.pipesize")) {
651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.pipesize = atol(args[1]);
657 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200658 else if (!strcmp(args[0], "tune.http.maxhdr")) {
659 if (*(args[1]) == 0) {
660 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
661 err_code |= ERR_ALERT | ERR_FATAL;
662 goto out;
663 }
664 global.tune.max_http_hdr = atol(args[1]);
665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 else if (!strcmp(args[0], "uid")) {
667 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200669 err_code |= ERR_ALERT;
670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 }
672 if (*(args[1]) == 0) {
673 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT | ERR_FATAL;
675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 }
677 global.uid = atol(args[1]);
678 }
679 else if (!strcmp(args[0], "gid")) {
680 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200681 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT;
683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685 if (*(args[1]) == 0) {
686 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200689 }
690 global.gid = atol(args[1]);
691 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200692 /* user/group name handling */
693 else if (!strcmp(args[0], "user")) {
694 struct passwd *ha_user;
695 if (global.uid != 0) {
696 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT;
698 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200699 }
700 errno = 0;
701 ha_user = getpwnam(args[1]);
702 if (ha_user != NULL) {
703 global.uid = (int)ha_user->pw_uid;
704 }
705 else {
706 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 +0200707 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200708 }
709 }
710 else if (!strcmp(args[0], "group")) {
711 struct group *ha_group;
712 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200713 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200716 }
717 errno = 0;
718 ha_group = getgrnam(args[1]);
719 if (ha_group != NULL) {
720 global.gid = (int)ha_group->gr_gid;
721 }
722 else {
723 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 +0200724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200725 }
726 }
727 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "nbproc")) {
729 if (global.nbproc != 0) {
730 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200731 err_code |= ERR_ALERT;
732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 }
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 global.nbproc = atol(args[1]);
740 }
741 else if (!strcmp(args[0], "maxconn")) {
742 if (global.maxconn != 0) {
743 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT;
745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 }
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 global.maxconn = atol(args[1]);
753#ifdef SYSTEM_MAXCONN
754 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
755 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);
756 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759#endif /* SYSTEM_MAXCONN */
760 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200761 else if (!strcmp(args[0], "maxsslconn")) {
762#ifdef USE_OPENSSL
763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.maxsslconn = atol(args[1]);
769#else
Emeric Brun0914df82012-10-02 18:45:42 +0200770 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200773#endif
774 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200775 else if (!strcmp(args[0], "maxconnrate")) {
776 if (global.cps_lim != 0) {
777 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT;
779 goto out;
780 }
781 if (*(args[1]) == 0) {
782 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786 global.cps_lim = atol(args[1]);
787 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100788 else if (!strcmp(args[0], "maxpipes")) {
789 if (global.maxpipes != 0) {
790 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200791 err_code |= ERR_ALERT;
792 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100793 }
794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100798 }
799 global.maxpipes = atol(args[1]);
800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 else if (!strcmp(args[0], "ulimit-n")) {
802 if (global.rlimit_nofile != 0) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200804 err_code |= ERR_ALERT;
805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 global.rlimit_nofile = atol(args[1]);
813 }
814 else if (!strcmp(args[0], "chroot")) {
815 if (global.chroot != NULL) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 }
825 global.chroot = strdup(args[1]);
826 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200827 else if (!strcmp(args[0], "description")) {
828 int i, len=0;
829 char *d;
830
831 if (!*args[1]) {
832 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837
838 for(i=1; *args[i]; i++)
839 len += strlen(args[i])+1;
840
841 if (global.desc)
842 free(global.desc);
843
844 global.desc = d = (char *)calloc(1, len);
845
846 d += sprintf(d, "%s", args[1]);
847 for(i=2; *args[i]; i++)
848 d += sprintf(d, " %s", args[i]);
849 }
850 else if (!strcmp(args[0], "node")) {
851 int i;
852 char c;
853
854 for (i=0; args[1][i]; i++) {
855 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100856 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
857 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200858 break;
859 }
860
861 if (!i || args[1][i]) {
862 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
863 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
864 file, linenum, args[0]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
867 }
868
869 if (global.node)
870 free(global.node);
871
872 global.node = strdup(args[1]);
873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874 else if (!strcmp(args[0], "pidfile")) {
875 if (global.pidfile != NULL) {
876 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT;
878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880 if (*(args[1]) == 0) {
881 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 }
885 global.pidfile = strdup(args[1]);
886 }
Emeric Bruned760922010-10-22 17:59:25 +0200887 else if (!strcmp(args[0], "unix-bind")) {
888 int cur_arg = 1;
889 while (*(args[cur_arg])) {
890 if (!strcmp(args[cur_arg], "prefix")) {
891 if (global.unix_bind.prefix != NULL) {
892 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
893 err_code |= ERR_ALERT;
894 cur_arg += 2;
895 continue;
896 }
897
898 if (*(args[cur_arg+1]) == 0) {
899 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
902 }
903 global.unix_bind.prefix = strdup(args[cur_arg+1]);
904 cur_arg += 2;
905 continue;
906 }
907
908 if (!strcmp(args[cur_arg], "mode")) {
909
910 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
911 cur_arg += 2;
912 continue;
913 }
914
915 if (!strcmp(args[cur_arg], "uid")) {
916
917 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
918 cur_arg += 2;
919 continue;
920 }
921
922 if (!strcmp(args[cur_arg], "gid")) {
923
924 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
925 cur_arg += 2;
926 continue;
927 }
928
929 if (!strcmp(args[cur_arg], "user")) {
930 struct passwd *user;
931
932 user = getpwnam(args[cur_arg + 1]);
933 if (!user) {
934 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
935 file, linenum, args[0], args[cur_arg + 1 ]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939
940 global.unix_bind.ux.uid = user->pw_uid;
941 cur_arg += 2;
942 continue;
943 }
944
945 if (!strcmp(args[cur_arg], "group")) {
946 struct group *group;
947
948 group = getgrnam(args[cur_arg + 1]);
949 if (!group) {
950 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
951 file, linenum, args[0], args[cur_arg + 1 ]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955
956 global.unix_bind.ux.gid = group->gr_gid;
957 cur_arg += 2;
958 continue;
959 }
960
Willy Tarreaub48f9582011-09-05 01:17:06 +0200961 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200962 file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 }
William Lallemand0f99e342011-10-12 17:50:54 +0200967 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
968 /* delete previous herited or defined syslog servers */
969 struct logsrv *back;
970 struct logsrv *tmp;
971
972 if (*(args[1]) != 0) {
973 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977
978 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
979 LIST_DEL(&tmp->list);
980 free(tmp);
981 }
982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200984 struct logsrv *logsrv;
985
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 if (*(args[1]) == 0 || *(args[2]) == 0) {
987 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 }
William Lallemand0f99e342011-10-12 17:50:54 +0200991
992 logsrv = calloc(1, sizeof(struct logsrv));
993
994 logsrv->facility = get_log_facility(args[2]);
995 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200996 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200997 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200998 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000
William Lallemand0f99e342011-10-12 17:50:54 +02001001 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001002 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001003 logsrv->level = get_log_level(args[3]);
1004 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001007 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 }
1009 }
1010
William Lallemand0f99e342011-10-12 17:50:54 +02001011 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001012 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001013 logsrv->minlvl = get_log_level(args[4]);
1014 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001015 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001017 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001018 }
1019 }
1020
Robert Tsai81ae1952007-12-05 10:47:29 +01001021 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001022 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001023 if (!sk) {
1024 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001025 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001026 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001027 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001028 goto out;
1029 }
William Lallemand0f99e342011-10-12 17:50:54 +02001030 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001031 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001032 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001033 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001034 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001036 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001037 goto out;
1038 }
William Lallemand0f99e342011-10-12 17:50:54 +02001039 logsrv->addr = *sk;
1040 if (!get_host_port(&logsrv->addr))
1041 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043
William Lallemand0f99e342011-10-12 17:50:54 +02001044 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001045 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001046 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1047 char *name;
1048 int len;
1049
1050 if (global.log_send_hostname != NULL) {
1051 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1052 err_code |= ERR_ALERT;
1053 goto out;
1054 }
1055
1056 if (*(args[1]))
1057 name = args[1];
1058 else
1059 name = hostname;
1060
1061 len = strlen(name);
1062
1063 /* We'll add a space after the name to respect the log format */
1064 free(global.log_send_hostname);
1065 global.log_send_hostname = malloc(len + 2);
1066 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1067 }
Kevinm48936af2010-12-22 16:08:21 +00001068 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
1073 }
1074 free(global.log_tag);
1075 global.log_tag = strdup(args[1]);
1076 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001077 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1078 if (global.spread_checks != 0) {
1079 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001080 err_code |= ERR_ALERT;
1081 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001082 }
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001087 }
1088 global.spread_checks = atol(args[1]);
1089 if (global.spread_checks < 0 || global.spread_checks > 50) {
1090 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001091 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 }
1094 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001095 struct cfg_kw_list *kwl;
1096 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001097 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001098
1099 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1100 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1101 if (kwl->kw[index].section != CFG_GLOBAL)
1102 continue;
1103 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1104 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001105 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001106 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001107 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001108 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001109 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001111 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001112 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001113 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001114 err_code |= ERR_WARN;
1115 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001116 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001118 }
1119 }
1120 }
1121
Willy Tarreaubaaee002006-06-26 02:48:02 +02001122 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001125
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001127 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129}
1130
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001131void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001133 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 defproxy.mode = PR_MODE_TCP;
1135 defproxy.state = PR_STNEW;
1136 defproxy.maxconn = cfg_maxpconn;
1137 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001138
1139 defproxy.defsrv.inter = DEF_CHKINTR;
1140 defproxy.defsrv.fastinter = 0;
1141 defproxy.defsrv.downinter = 0;
1142 defproxy.defsrv.rise = DEF_RISETIME;
1143 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001144 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001145 defproxy.defsrv.maxqueue = 0;
1146 defproxy.defsrv.minconn = 0;
1147 defproxy.defsrv.maxconn = 0;
1148 defproxy.defsrv.slowstart = 0;
1149 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1150 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1151 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152}
1153
Willy Tarreauade5ec42010-01-28 19:33:49 +01001154
1155static int create_cond_regex_rule(const char *file, int line,
1156 struct proxy *px, int dir, int action, int flags,
1157 const char *cmd, const char *reg, const char *repl,
1158 const char **cond_start)
1159{
1160 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001161 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001162 const char *err;
1163 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001164 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001165
1166 if (px == &defproxy) {
1167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1168 err_code |= ERR_ALERT | ERR_FATAL;
1169 goto err;
1170 }
1171
1172 if (*reg == 0) {
1173 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto err;
1176 }
1177
1178 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1179 err_code |= ERR_WARN;
1180
Willy Tarreau5321c422010-01-28 20:35:13 +01001181 if (cond_start &&
1182 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001183 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1184 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1185 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto err;
1188 }
1189 }
1190 else if (cond_start && **cond_start) {
1191 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1192 file, line, cmd, *cond_start);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto err;
1195 }
1196
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001197 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001198 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001199 else
1200 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001201
Willy Tarreauade5ec42010-01-28 19:33:49 +01001202 preg = calloc(1, sizeof(regex_t));
1203 if (!preg) {
1204 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1205 err_code = ERR_ALERT | ERR_FATAL;
1206 goto err;
1207 }
1208
1209 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1210 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1211 err_code = ERR_ALERT | ERR_FATAL;
1212 goto err;
1213 }
1214
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001215 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001216 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001217 if (repl && err) {
1218 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1219 file, line, cmd, *err);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto err;
1222 }
1223
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001224 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001225 err_code |= ERR_WARN;
1226
Willy Tarreauf4068b62012-05-08 17:37:49 +02001227 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001228 return err_code;
1229 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001230 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001231 free(preg);
1232 return err_code;
1233}
1234
Willy Tarreaubaaee002006-06-26 02:48:02 +02001235/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001236 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001237 * Returns the error code, 0 if OK, or any combination of :
1238 * - ERR_ABORT: must abort ASAP
1239 * - ERR_FATAL: we can continue parsing but not start the service
1240 * - ERR_WARN: a warning has been emitted
1241 * - ERR_ALERT: an alert has been emitted
1242 * Only the two first ones can stop processing, the two others are just
1243 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001244 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001245int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1246{
1247 static struct peers *curpeers = NULL;
1248 struct peer *newpeer = NULL;
1249 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001250 struct bind_conf *bind_conf;
1251 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001252 int err_code = 0;
1253
1254 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1255
1256 err = invalid_char(args[1]);
1257 if (err) {
1258 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1259 file, linenum, *err, args[0], args[1]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 }
1262
1263 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1264 /*
1265 * If there are two proxies with the same name only following
1266 * combinations are allowed:
1267 */
1268 if (strcmp(curpeers->id, args[1]) == 0) {
1269 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1270 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1271 err_code |= ERR_WARN;
1272 }
1273 }
1274
1275 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1276 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1277 err_code |= ERR_ALERT | ERR_ABORT;
1278 goto out;
1279 }
1280
1281 curpeers->next = peers;
1282 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001283 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001284 curpeers->conf.line = linenum;
1285 curpeers->last_change = now.tv_sec;
1286 curpeers->id = strdup(args[1]);
1287 }
1288 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1289 char *rport, *raddr;
1290 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001291 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001292 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001293
1294 if (!*args[2]) {
1295 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1296 file, linenum, args[0]);
1297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
1299 }
1300
1301 err = invalid_char(args[1]);
1302 if (err) {
1303 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1304 file, linenum, *err, args[1]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308
1309 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1311 err_code |= ERR_ALERT | ERR_ABORT;
1312 goto out;
1313 }
1314
1315 /* the peers are linked backwards first */
1316 curpeers->count++;
1317 newpeer->next = curpeers->remote;
1318 curpeers->remote = newpeer;
1319 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001320 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001321 newpeer->conf.line = linenum;
1322
1323 newpeer->last_change = now.tv_sec;
1324 newpeer->id = strdup(args[1]);
1325
1326 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001327 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001328 if (rport) {
1329 *rport++ = 0;
1330 realport = atol(rport);
1331 }
1332 if (!realport) {
1333 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
1337
Willy Tarreaufab5a432011-03-04 15:31:53 +01001338 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 free(raddr);
1340 if (!sk) {
1341 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001346 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001347 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001348 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001349
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001350 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001351 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1352 file, linenum, newpeer->addr.ss_family, args[2]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001357 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001358
1359 if (strcmp(newpeer->id, localpeer) == 0) {
1360 /* Current is local peer, it define a frontend */
1361 newpeer->local = 1;
1362
1363 if (!curpeers->peers_fe) {
1364 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1365 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1366 err_code |= ERR_ALERT | ERR_ABORT;
1367 goto out;
1368 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001369
Willy Tarreau237250c2011-07-29 01:49:03 +02001370 init_new_proxy(curpeers->peers_fe);
1371 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001372
1373 curpeers->peers_fe->last_change = now.tv_sec;
1374 curpeers->peers_fe->id = strdup(args[1]);
1375 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001376 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001377 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1378 curpeers->peers_fe->timeout.connect = 5000;
1379 curpeers->peers_fe->accept = peer_accept;
1380 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001381
1382 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1383
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001384 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1385 if (err_msg && *err_msg) {
1386 indent_msg(&err_msg, 2);
1387 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1388 }
1389 else
1390 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1391 file, linenum, args[0], args[1], args[2]);
1392 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001393 err_code |= ERR_FATAL;
1394 goto out;
1395 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001396
1397 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1398 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1399 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1400 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1401 l->accept = session_accept;
1402 l->handler = process_session;
1403 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1404 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1405 global.maxsock += l->maxconn;
1406 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001407 }
1408 }
1409 } /* neither "peer" nor "peers" */
1410 else if (*args[0] != 0) {
1411 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1412 err_code |= ERR_ALERT | ERR_FATAL;
1413 goto out;
1414 }
1415
1416out:
1417 return err_code;
1418}
1419
1420
Willy Tarreau3842f002009-06-14 11:39:52 +02001421int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422{
1423 static struct proxy *curproxy = NULL;
1424 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001425 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001426 int rc;
1427 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001428 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001429 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001430 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001431 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001432 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433
Willy Tarreau977b8e42006-12-29 14:19:17 +01001434 if (!strcmp(args[0], "listen"))
1435 rc = PR_CAP_LISTEN;
1436 else if (!strcmp(args[0], "frontend"))
1437 rc = PR_CAP_FE | PR_CAP_RS;
1438 else if (!strcmp(args[0], "backend"))
1439 rc = PR_CAP_BE | PR_CAP_RS;
1440 else if (!strcmp(args[0], "ruleset"))
1441 rc = PR_CAP_RS;
1442 else
1443 rc = PR_CAP_NONE;
1444
1445 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 if (!*args[1]) {
1447 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1448 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001450 err_code |= ERR_ALERT | ERR_ABORT;
1451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001453
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001454 err = invalid_char(args[1]);
1455 if (err) {
1456 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1457 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001458 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001459 }
1460
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001461 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1462 /*
1463 * If there are two proxies with the same name only following
1464 * combinations are allowed:
1465 *
1466 * listen backend frontend ruleset
1467 * listen - - - -
1468 * backend - - OK -
1469 * frontend - OK - -
1470 * ruleset - - - -
1471 */
1472
1473 if (!strcmp(curproxy->id, args[1]) &&
1474 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1475 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001476 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1477 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1478 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001479 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001480 }
1481 }
1482
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1484 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001485 err_code |= ERR_ALERT | ERR_ABORT;
1486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001488
Willy Tarreau97cb7802010-01-03 20:23:58 +01001489 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 curproxy->next = proxy;
1491 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001492 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001493 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001494 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497
1498 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001499 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001500 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001501 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001502
Willy Tarreau4348fad2012-09-20 16:48:07 +02001503 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1504
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001505 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1506 if (err_msg && *err_msg) {
1507 indent_msg(&err_msg, 2);
1508 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1509 }
1510 else
1511 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1512 file, linenum, args[0], args[1], args[2]);
1513 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001514 err_code |= ERR_FATAL;
1515 goto out;
1516 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001517
Willy Tarreau4348fad2012-09-20 16:48:07 +02001518 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001519 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001520 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 }
1522
1523 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001524 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001525 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001526
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001529 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001530 curproxy->no_options = defproxy.no_options;
1531 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001532 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001533 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001534 curproxy->except_net = defproxy.except_net;
1535 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001536 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001537 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001539 if (defproxy.fwdfor_hdr_len) {
1540 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1541 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1542 }
1543
Willy Tarreaub86db342009-11-30 11:50:16 +01001544 if (defproxy.orgto_hdr_len) {
1545 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1546 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1547 }
1548
Mark Lamourinec2247f02012-01-04 13:02:01 -05001549 if (defproxy.server_id_hdr_len) {
1550 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1551 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1552 }
1553
Willy Tarreau977b8e42006-12-29 14:19:17 +01001554 if (curproxy->cap & PR_CAP_FE) {
1555 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001556 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001557 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558
1559 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001560 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1561 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001562
1563 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 if (curproxy->cap & PR_CAP_BE) {
1567 curproxy->fullconn = defproxy.fullconn;
1568 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001570 if (defproxy.check_req) {
1571 curproxy->check_req = calloc(1, defproxy.check_len);
1572 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1573 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001574 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001576 if (defproxy.expect_str) {
1577 curproxy->expect_str = strdup(defproxy.expect_str);
1578 if (defproxy.expect_regex) {
1579 /* note: this regex is known to be valid */
1580 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1581 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1582 }
1583 }
1584
Willy Tarreau67402132012-05-31 20:40:20 +02001585 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001586 if (defproxy.cookie_name)
1587 curproxy->cookie_name = strdup(defproxy.cookie_name);
1588 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001589 if (defproxy.cookie_domain)
1590 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001591
Willy Tarreau31936852010-10-06 16:59:56 +02001592 if (defproxy.cookie_maxidle)
1593 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1594
1595 if (defproxy.cookie_maxlife)
1596 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1597
Emeric Brun647caf12009-06-30 17:57:00 +02001598 if (defproxy.rdp_cookie_name)
1599 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1600 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1601
Willy Tarreau01732802007-11-01 22:48:15 +01001602 if (defproxy.url_param_name)
1603 curproxy->url_param_name = strdup(defproxy.url_param_name);
1604 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001605
Benoitaffb4812009-03-25 13:02:10 +01001606 if (defproxy.hh_name)
1607 curproxy->hh_name = strdup(defproxy.hh_name);
1608 curproxy->hh_len = defproxy.hh_len;
1609 curproxy->hh_match_domain = defproxy.hh_match_domain;
1610
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001611 if (defproxy.iface_name)
1612 curproxy->iface_name = strdup(defproxy.iface_name);
1613 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001616 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 if (defproxy.capture_name)
1618 curproxy->capture_name = strdup(defproxy.capture_name);
1619 curproxy->capture_namelen = defproxy.capture_namelen;
1620 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622
Willy Tarreau977b8e42006-12-29 14:19:17 +01001623 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001624 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001625 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001626 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001627 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 curproxy->uri_auth = defproxy.uri_auth;
1629 curproxy->mon_net = defproxy.mon_net;
1630 curproxy->mon_mask = defproxy.mon_mask;
1631 if (defproxy.monitor_uri)
1632 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1633 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001634 if (defproxy.defbe.name)
1635 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001636
1637 /* get either a pointer to the logformat string or a copy of it */
1638 curproxy->logformat_string = defproxy.logformat_string;
1639 if (curproxy->logformat_string &&
1640 curproxy->logformat_string != default_http_log_format &&
1641 curproxy->logformat_string != default_tcp_log_format &&
1642 curproxy->logformat_string != clf_http_log_format)
1643 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001644 }
1645
1646 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001647 curproxy->timeout.connect = defproxy.timeout.connect;
1648 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001649 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001650 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001651 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001652 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001653 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001654 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001655 curproxy->source_addr = defproxy.source_addr;
1656 }
1657
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001659
1660 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001661 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001662 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001663 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001664 LIST_INIT(&node->list);
1665 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1666 }
1667
Willy Tarreau196729e2012-05-31 19:30:26 +02001668 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1669 if (curproxy->uniqueid_format_string)
1670 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001671
1672 /* copy default header unique id */
1673 if (defproxy.header_unique_id)
1674 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1675
William Lallemand82fe75c2012-10-23 10:25:10 +02001676 /* default compression options */
1677 if (defproxy.comp != NULL) {
1678 curproxy->comp = calloc(1, sizeof(struct comp));
1679 curproxy->comp->algos = defproxy.comp->algos;
1680 curproxy->comp->types = defproxy.comp->types;
1681 }
1682
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001684 curproxy->conf.used_listener_id = EB_ROOT;
1685 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001686
Willy Tarreau93893792009-07-23 13:19:11 +02001687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
1689 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1690 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001691 /* FIXME-20070101: we should do this too at the end of the
1692 * config parsing to free all default values.
1693 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001694 free(defproxy.check_req);
1695 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001696 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001697 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001698 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001699 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001700 free(defproxy.capture_name);
1701 free(defproxy.monitor_uri);
1702 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001703 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001704 free(defproxy.fwdfor_hdr_name);
1705 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001706 free(defproxy.orgto_hdr_name);
1707 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001708 free(defproxy.server_id_hdr_name);
1709 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001710 free(defproxy.expect_str);
1711 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001712
Willy Tarreau39b06652012-06-01 10:58:06 +02001713 if (defproxy.logformat_string != default_http_log_format &&
1714 defproxy.logformat_string != default_tcp_log_format &&
1715 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001716 free(defproxy.logformat_string);
1717
1718 free(defproxy.uniqueid_format_string);
1719
Willy Tarreaua534fea2008-08-03 12:19:50 +02001720 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001721 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001722
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 /* we cannot free uri_auth because it might already be used */
1724 init_default_instance();
1725 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001726 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 }
1729 else if (curproxy == NULL) {
1730 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 }
1734
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735
1736 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001738 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001739 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001740 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001741
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 if (curproxy == &defproxy) {
1743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001748 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749
Emeric Bruned760922010-10-22 17:59:25 +02001750 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001751 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001756
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001757 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001758 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001759
1760 /* NOTE: the following line might create several listeners if there
1761 * are comma-separated IPs or port ranges. So all further processing
1762 * will have to be applied to all listeners created after last_listen.
1763 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001764 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1765 if (err_msg && *err_msg) {
1766 indent_msg(&err_msg, 2);
1767 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1768 }
1769 else
1770 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1771 file, linenum, args[0], args[1]);
1772 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001776
Willy Tarreau4348fad2012-09-20 16:48:07 +02001777 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1778 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001779 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001780 }
1781
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001782 cur_arg = 2;
1783 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001784 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001785 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001786 char *err;
1787
Willy Tarreau26982662012-09-12 23:17:10 +02001788 kw = bind_find_kw(args[cur_arg]);
1789 if (kw) {
1790 char *err = NULL;
1791 int code;
1792
1793 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001794 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1795 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001796 cur_arg += 1 + kw->skip ;
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
1800
Willy Tarreau4348fad2012-09-20 16:48:07 +02001801 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001802 err_code |= code;
1803
1804 if (code) {
1805 if (err && *err) {
1806 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001807 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001808 }
1809 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001810 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1811 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001812 if (code & ERR_FATAL) {
1813 free(err);
1814 cur_arg += 1 + kw->skip;
1815 goto out;
1816 }
1817 }
1818 free(err);
1819 cur_arg += 1 + kw->skip;
1820 continue;
1821 }
1822
Willy Tarreau8638f482012-09-18 18:01:17 +02001823 err = NULL;
1824 if (!bind_dumped) {
1825 bind_dump_kws(&err);
1826 indent_msg(&err, 4);
1827 bind_dumped = 1;
1828 }
1829
1830 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1831 file, linenum, args[0], args[1], args[cur_arg],
1832 err ? " Registered keywords :" : "", err ? err : "");
1833 free(err);
1834
Willy Tarreau93893792009-07-23 13:19:11 +02001835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001837 }
Willy Tarreau93893792009-07-23 13:19:11 +02001838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839 }
1840 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1841 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1842 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001847 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850 /* flush useless bits */
1851 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001853 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001854 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001855 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001856 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001857
Willy Tarreau1c47f852006-07-09 08:22:27 +02001858 if (!*args[1]) {
1859 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1860 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001863 }
1864
Willy Tarreaua534fea2008-08-03 12:19:50 +02001865 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001866 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001867 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001868 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001869 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1870
Willy Tarreau93893792009-07-23 13:19:11 +02001871 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1874 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1875 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1876 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1877 else {
1878 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001879 err_code |= ERR_ALERT | ERR_FATAL;
1880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 }
1882 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001883 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001884 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001885
1886 if (curproxy == &defproxy) {
1887 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1888 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001891 }
1892
1893 if (!*args[1]) {
1894 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001898 }
1899
1900 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001901 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001902
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001903 if (curproxy->uuid <= 0) {
1904 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001905 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001908 }
1909
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001910 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1911 if (node) {
1912 struct proxy *target = container_of(node, struct proxy, conf.id);
1913 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1914 file, linenum, proxy_type_str(curproxy), curproxy->id,
1915 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
1918 }
1919 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001920 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001921 else if (!strcmp(args[0], "description")) {
1922 int i, len=0;
1923 char *d;
1924
Cyril Bonté99ed3272010-01-24 23:29:44 +01001925 if (curproxy == &defproxy) {
1926 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1927 file, linenum, args[0]);
1928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
1931
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001932 if (!*args[1]) {
1933 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1934 file, linenum, args[0]);
1935 return -1;
1936 }
1937
1938 for(i=1; *args[i]; i++)
1939 len += strlen(args[i])+1;
1940
1941 d = (char *)calloc(1, len);
1942 curproxy->desc = d;
1943
1944 d += sprintf(d, "%s", args[1]);
1945 for(i=2; *args[i]; i++)
1946 d += sprintf(d, " %s", args[i]);
1947
1948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1950 curproxy->state = PR_STSTOPPED;
1951 }
1952 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1953 curproxy->state = PR_STNEW;
1954 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001955 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1956 int cur_arg = 1;
1957 unsigned int set = 0;
1958
1959 while (*args[cur_arg]) {
1960 int u;
1961 if (strcmp(args[cur_arg], "all") == 0) {
1962 set = 0;
1963 break;
1964 }
1965 else if (strcmp(args[cur_arg], "odd") == 0) {
1966 set |= 0x55555555;
1967 }
1968 else if (strcmp(args[cur_arg], "even") == 0) {
1969 set |= 0xAAAAAAAA;
1970 }
1971 else {
1972 u = str2uic(args[cur_arg]);
1973 if (u < 1 || u > 32) {
1974 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1975 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001978 }
1979 if (u > global.nbproc) {
1980 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1981 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001983 }
1984 set |= 1 << (u - 1);
1985 }
1986 cur_arg++;
1987 }
1988 curproxy->bind_proc = set;
1989 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001990 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001991 if (curproxy == &defproxy) {
1992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001993 err_code |= ERR_ALERT | ERR_FATAL;
1994 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001995 }
1996
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001997 err = invalid_char(args[1]);
1998 if (err) {
1999 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2000 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002002 }
2003
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002004 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2005 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2006 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002009 }
2010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2012 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013
Willy Tarreau977b8e42006-12-29 14:19:17 +01002014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002016
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 if (*(args[1]) == 0) {
2018 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002023
Willy Tarreau67402132012-05-31 20:40:20 +02002024 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002025 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002026 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002027 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 curproxy->cookie_name = strdup(args[1]);
2029 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002030
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 cur_arg = 2;
2032 while (*(args[cur_arg])) {
2033 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002034 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 }
2036 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002037 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
2039 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002040 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
2042 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002043 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 }
2045 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002046 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002048 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002049 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002052 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002054 else if (!strcmp(args[cur_arg], "httponly")) {
2055 curproxy->ck_opts |= PR_CK_HTTPONLY;
2056 }
2057 else if (!strcmp(args[cur_arg], "secure")) {
2058 curproxy->ck_opts |= PR_CK_SECURE;
2059 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002060 else if (!strcmp(args[cur_arg], "domain")) {
2061 if (!*args[cur_arg + 1]) {
2062 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2063 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002066 }
2067
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002068 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002069 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002070 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2071 " dots nor does not start with a dot."
2072 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002073 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002074 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002075 }
2076
2077 err = invalid_domainchar(args[cur_arg + 1]);
2078 if (err) {
2079 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2080 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_ALERT | ERR_FATAL;
2082 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002083 }
2084
Willy Tarreau68a897b2009-12-03 23:28:34 +01002085 if (!curproxy->cookie_domain) {
2086 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2087 } else {
2088 /* one domain was already specified, add another one by
2089 * building the string which will be returned along with
2090 * the cookie.
2091 */
2092 char *new_ptr;
2093 int new_len = strlen(curproxy->cookie_domain) +
2094 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2095 new_ptr = malloc(new_len);
2096 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2097 free(curproxy->cookie_domain);
2098 curproxy->cookie_domain = new_ptr;
2099 }
Willy Tarreau31936852010-10-06 16:59:56 +02002100 cur_arg++;
2101 }
2102 else if (!strcmp(args[cur_arg], "maxidle")) {
2103 unsigned int maxidle;
2104 const char *res;
2105
2106 if (!*args[cur_arg + 1]) {
2107 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2108 file, linenum, args[cur_arg]);
2109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
2111 }
2112
2113 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2114 if (res) {
2115 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2116 file, linenum, *res, args[cur_arg]);
2117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
2119 }
2120 curproxy->cookie_maxidle = maxidle;
2121 cur_arg++;
2122 }
2123 else if (!strcmp(args[cur_arg], "maxlife")) {
2124 unsigned int maxlife;
2125 const char *res;
2126
2127 if (!*args[cur_arg + 1]) {
2128 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2129 file, linenum, args[cur_arg]);
2130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
2132 }
2133
2134 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2135 if (res) {
2136 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2137 file, linenum, *res, args[cur_arg]);
2138 err_code |= ERR_ALERT | ERR_FATAL;
2139 goto out;
2140 }
2141 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 cur_arg++;
2143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002145 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 +02002146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 }
2150 cur_arg++;
2151 }
Willy Tarreau67402132012-05-31 20:40:20 +02002152 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2154 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002155 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 }
2157
Willy Tarreau67402132012-05-31 20:40:20 +02002158 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2160 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002163
Willy Tarreau67402132012-05-31 20:40:20 +02002164 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002165 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2166 file, linenum);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002169 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002170 else if (!strcmp(args[0], "persist")) { /* persist */
2171 if (*(args[1]) == 0) {
2172 Alert("parsing [%s:%d] : missing persist method.\n",
2173 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002176 }
2177
2178 if (!strncmp(args[1], "rdp-cookie", 10)) {
2179 curproxy->options2 |= PR_O2_RDPC_PRST;
2180
Emeric Brunb982a3d2010-01-04 15:45:53 +01002181 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002182 const char *beg, *end;
2183
2184 beg = args[1] + 11;
2185 end = strchr(beg, ')');
2186
2187 if (!end || end == beg) {
2188 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2189 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_ALERT | ERR_FATAL;
2191 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002192 }
2193
2194 free(curproxy->rdp_cookie_name);
2195 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2196 curproxy->rdp_cookie_len = end-beg;
2197 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002198 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002199 free(curproxy->rdp_cookie_name);
2200 curproxy->rdp_cookie_name = strdup("msts");
2201 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2202 }
2203 else { /* syntax */
2204 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2205 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002208 }
2209 }
2210 else {
2211 Alert("parsing [%s:%d] : unknown persist method.\n",
2212 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
2214 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002215 }
2216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002218 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002220 if (curproxy == &defproxy) {
2221 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
2224 }
2225
Willy Tarreau977b8e42006-12-29 14:19:17 +01002226 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002228
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002230 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002236 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 curproxy->appsession_name = strdup(args[1]);
2238 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2239 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002240 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2241 if (err) {
2242 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2243 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002246 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002247 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002248
Willy Tarreau51041c72007-09-09 21:56:53 +02002249 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_ABORT;
2252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002254
2255 cur_arg = 6;
2256 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002257 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2258 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002259 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002260 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002261 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002262 } else if (!strcmp(args[cur_arg], "prefix")) {
2263 curproxy->options2 |= PR_O2_AS_PFX;
2264 } else if (!strcmp(args[cur_arg], "mode")) {
2265 if (!*args[cur_arg + 1]) {
2266 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2267 file, linenum, args[0], args[cur_arg]);
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271
2272 cur_arg++;
2273 if (!strcmp(args[cur_arg], "query-string")) {
2274 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2275 curproxy->options2 |= PR_O2_AS_M_QS;
2276 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2277 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2278 curproxy->options2 |= PR_O2_AS_M_PP;
2279 } else {
2280 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002285 cur_arg++;
2286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287 } /* Url App Session */
2288 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002289 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002293 if (curproxy == &defproxy) {
2294 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 if (*(args[4]) == 0) {
2300 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2301 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->capture_name = strdup(args[2]);
2307 curproxy->capture_namelen = strlen(curproxy->capture_name);
2308 curproxy->capture_len = atol(args[4]);
2309 if (curproxy->capture_len >= CAPTURE_LEN) {
2310 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2311 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 curproxy->capture_len = CAPTURE_LEN - 1;
2314 }
2315 curproxy->to_log |= LW_COOKIE;
2316 }
2317 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2318 struct cap_hdr *hdr;
2319
2320 if (curproxy == &defproxy) {
2321 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 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
2325
2326 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2327 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2328 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
2332
2333 hdr = calloc(sizeof(struct cap_hdr), 1);
2334 hdr->next = curproxy->req_cap;
2335 hdr->name = strdup(args[3]);
2336 hdr->namelen = strlen(args[3]);
2337 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002338 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 hdr->index = curproxy->nb_req_cap++;
2340 curproxy->req_cap = hdr;
2341 curproxy->to_log |= LW_REQHDR;
2342 }
2343 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2344 struct cap_hdr *hdr;
2345
2346 if (curproxy == &defproxy) {
2347 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 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 }
2351
2352 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2353 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2354 file, linenum, args[0], args[1]);
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 hdr = calloc(sizeof(struct cap_hdr), 1);
2359 hdr->next = curproxy->rsp_cap;
2360 hdr->name = strdup(args[3]);
2361 hdr->namelen = strlen(args[3]);
2362 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002363 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 hdr->index = curproxy->nb_rsp_cap++;
2365 curproxy->rsp_cap = hdr;
2366 curproxy->to_log |= LW_RSPHDR;
2367 }
2368 else {
2369 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 if (*(args[1]) == 0) {
2380 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 curproxy->conn_retries = atol(args[1]);
2386 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002387 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002388 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002389
2390 if (curproxy == &defproxy) {
2391 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395
Willy Tarreauff011f22011-01-06 17:51:27 +01002396 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002397 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2398 file, linenum, args[0]);
2399 err_code |= ERR_WARN;
2400 }
2401
Willy Tarreauff011f22011-01-06 17:51:27 +01002402 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002403
Willy Tarreauff011f22011-01-06 17:51:27 +01002404 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002405 err_code |= ERR_ALERT | ERR_ABORT;
2406 goto out;
2407 }
2408
Willy Tarreauff011f22011-01-06 17:51:27 +01002409 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2410 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002411 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002412 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2413 /* set the header name and length into the proxy structure */
2414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2415 err_code |= ERR_WARN;
2416
2417 if (!*args[1]) {
2418 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2419 file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
2424 /* set the desired header name */
2425 free(curproxy->server_id_hdr_name);
2426 curproxy->server_id_hdr_name = strdup(args[1]);
2427 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2428 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002429 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002430 if (curproxy == &defproxy) {
2431 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002434 }
2435
Willy Tarreauef6494c2010-01-28 17:12:36 +01002436 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002437 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002441 }
2442
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002443 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2444 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2445 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002448 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002449
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002450 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002451 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002452 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002453 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002454 struct redirect_rule *rule;
2455 int cur_arg;
2456 int type = REDIRECT_TYPE_NONE;
2457 int code = 302;
2458 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002459 char *cookie = NULL;
2460 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002461 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002462
Cyril Bonté99ed3272010-01-24 23:29:44 +01002463 if (curproxy == &defproxy) {
2464 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002469 cur_arg = 1;
2470 while (*(args[cur_arg])) {
2471 if (!strcmp(args[cur_arg], "location")) {
2472 if (!*args[cur_arg + 1]) {
2473 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2474 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002477 }
2478
2479 type = REDIRECT_TYPE_LOCATION;
2480 cur_arg++;
2481 destination = args[cur_arg];
2482 }
2483 else if (!strcmp(args[cur_arg], "prefix")) {
2484 if (!*args[cur_arg + 1]) {
2485 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2486 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002489 }
2490
2491 type = REDIRECT_TYPE_PREFIX;
2492 cur_arg++;
2493 destination = args[cur_arg];
2494 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002495 else if (!strcmp(args[cur_arg], "scheme")) {
2496 if (!*args[cur_arg + 1]) {
2497 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2498 file, linenum, args[0], args[cur_arg]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
2503 type = REDIRECT_TYPE_SCHEME;
2504 cur_arg++;
2505 destination = args[cur_arg];
2506 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002507 else if (!strcmp(args[cur_arg], "set-cookie")) {
2508 if (!*args[cur_arg + 1]) {
2509 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2510 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002513 }
2514
2515 cur_arg++;
2516 cookie = args[cur_arg];
2517 cookie_set = 1;
2518 }
2519 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2520 if (!*args[cur_arg + 1]) {
2521 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2522 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002525 }
2526
2527 cur_arg++;
2528 cookie = args[cur_arg];
2529 cookie_set = 0;
2530 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002531 else if (!strcmp(args[cur_arg],"code")) {
2532 if (!*args[cur_arg + 1]) {
2533 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002537 }
2538 cur_arg++;
2539 code = atol(args[cur_arg]);
2540 if (code < 301 || code > 303) {
2541 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2542 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002545 }
2546 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002547 else if (!strcmp(args[cur_arg],"drop-query")) {
2548 flags |= REDIRECT_FLAG_DROP_QS;
2549 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002550 else if (!strcmp(args[cur_arg],"append-slash")) {
2551 flags |= REDIRECT_FLAG_APPEND_SLASH;
2552 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002553 else if (strcmp(args[cur_arg], "if") == 0 ||
2554 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002555 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002556 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002557 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2558 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 break;
2563 }
2564 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002565 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002566 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002569 }
2570 cur_arg++;
2571 }
2572
2573 if (type == REDIRECT_TYPE_NONE) {
2574 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2575 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 }
2579
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2581 rule->cond = cond;
2582 rule->rdr_str = strdup(destination);
2583 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002584 if (cookie) {
2585 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002586 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002587 */
2588 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002589 if (cookie_set) {
2590 rule->cookie_str = malloc(rule->cookie_len + 10);
2591 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2592 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2593 rule->cookie_len += 9;
2594 } else {
2595 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002596 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002597 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2598 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002599 }
2600 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 rule->type = type;
2602 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002603 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002604 LIST_INIT(&rule->list);
2605 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002606 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2607 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002609 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002610 struct switching_rule *rule;
2611
Willy Tarreaub099aca2008-10-12 17:26:37 +02002612 if (curproxy == &defproxy) {
2613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002616 }
2617
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002620
2621 if (*(args[1]) == 0) {
2622 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002625 }
2626
Willy Tarreauef6494c2010-01-28 17:12:36 +01002627 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002632 }
2633
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002634 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2635 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2636 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002639 }
2640
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002641 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002642
Willy Tarreau55ea7572007-06-17 19:56:27 +02002643 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2644 rule->cond = cond;
2645 rule->be.name = strdup(args[1]);
2646 LIST_INIT(&rule->list);
2647 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2648 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002649 else if (strcmp(args[0], "use-server") == 0) {
2650 struct server_rule *rule;
2651
2652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
2658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2659 err_code |= ERR_WARN;
2660
2661 if (*(args[1]) == 0) {
2662 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2668 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2669 file, linenum, args[0]);
2670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002674 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2675 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2676 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680
2681 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2682
2683 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2684 rule->cond = cond;
2685 rule->srv.name = strdup(args[1]);
2686 LIST_INIT(&rule->list);
2687 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2688 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2689 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002690 else if ((!strcmp(args[0], "force-persist")) ||
2691 (!strcmp(args[0], "ignore-persist"))) {
2692 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002693
2694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699
2700 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2701 err_code |= ERR_WARN;
2702
Willy Tarreauef6494c2010-01-28 17:12:36 +01002703 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2705 file, linenum, args[0]);
2706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
2708 }
2709
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002710 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2711 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2712 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002717 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002718
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002719 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002720 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002721 if (!strcmp(args[0], "force-persist")) {
2722 rule->type = PERSIST_TYPE_FORCE;
2723 } else {
2724 rule->type = PERSIST_TYPE_IGNORE;
2725 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002726 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002727 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002728 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 else if (!strcmp(args[0], "stick-table")) {
2730 int myidx = 1;
2731
Emeric Brun32da3c42010-09-23 18:39:19 +02002732 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002733 curproxy->table.type = (unsigned int)-1;
2734 while (*args[myidx]) {
2735 const char *err;
2736
2737 if (strcmp(args[myidx], "size") == 0) {
2738 myidx++;
2739 if (!*(args[myidx])) {
2740 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2741 file, linenum, args[myidx-1]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2746 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2747 file, linenum, *err, args[myidx-1]);
2748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002751 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002752 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002753 else if (strcmp(args[myidx], "peers") == 0) {
2754 myidx++;
2755 if (!*(args[myidx])) {
2756 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2757 file, linenum, args[myidx-1]);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761 curproxy->table.peers.name = strdup(args[myidx++]);
2762 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002763 else if (strcmp(args[myidx], "expire") == 0) {
2764 myidx++;
2765 if (!*(args[myidx])) {
2766 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2767 file, linenum, args[myidx-1]);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2772 if (err) {
2773 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2774 file, linenum, *err, args[myidx-1]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002779 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002780 }
2781 else if (strcmp(args[myidx], "nopurge") == 0) {
2782 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002783 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002784 }
2785 else if (strcmp(args[myidx], "type") == 0) {
2786 myidx++;
2787 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2788 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2789 file, linenum, args[myidx]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002793 /* myidx already points to next arg */
2794 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002795 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002796 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002797 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002798
2799 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002800 nw = args[myidx];
2801 while (*nw) {
2802 /* the "store" keyword supports a comma-separated list */
2803 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002804 sa = NULL; /* store arg */
2805 while (*nw && *nw != ',') {
2806 if (*nw == '(') {
2807 *nw = 0;
2808 sa = ++nw;
2809 while (*nw != ')') {
2810 if (!*nw) {
2811 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2812 file, linenum, args[0], cw);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816 nw++;
2817 }
2818 *nw = '\0';
2819 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002820 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002821 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002822 if (*nw)
2823 *nw++ = '\0';
2824 type = stktable_get_data_type(cw);
2825 if (type < 0) {
2826 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
Willy Tarreauac782882010-06-20 10:41:54 +02002831
2832 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2833 switch (err) {
2834 case PE_NONE: break;
2835 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002836 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2837 file, linenum, args[0], cw);
2838 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002839 break;
2840
2841 case PE_ARG_MISSING:
2842 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2843 file, linenum, args[0], cw);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846
2847 case PE_ARG_NOT_USED:
2848 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2849 file, linenum, args[0], cw);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852
2853 default:
2854 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2855 file, linenum, args[0], cw);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002858 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002859 }
2860 myidx++;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 else {
2863 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2864 file, linenum, args[myidx]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002868 }
2869
2870 if (!curproxy->table.size) {
2871 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2872 file, linenum);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
2877 if (curproxy->table.type == (unsigned int)-1) {
2878 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2879 file, linenum);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883 }
2884 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002885 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002886 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002887 int myidx = 0;
2888 const char *name = NULL;
2889 int flags;
2890
2891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
2897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2898 err_code |= ERR_WARN;
2899 goto out;
2900 }
2901
2902 myidx++;
2903 if ((strcmp(args[myidx], "store") == 0) ||
2904 (strcmp(args[myidx], "store-request") == 0)) {
2905 myidx++;
2906 flags = STK_IS_STORE;
2907 }
2908 else if (strcmp(args[myidx], "store-response") == 0) {
2909 myidx++;
2910 flags = STK_IS_STORE | STK_ON_RSP;
2911 }
2912 else if (strcmp(args[myidx], "match") == 0) {
2913 myidx++;
2914 flags = STK_IS_MATCH;
2915 }
2916 else if (strcmp(args[myidx], "on") == 0) {
2917 myidx++;
2918 flags = STK_IS_MATCH | STK_IS_STORE;
2919 }
2920 else {
2921 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925
2926 if (*(args[myidx]) == 0) {
2927 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931
David du Colombier7af46052012-05-16 14:16:48 +02002932 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002934 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002940 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2942 file, linenum, args[0], expr->fetch->kw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002944 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 goto out;
2946 }
2947 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002948 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2950 file, linenum, args[0], expr->fetch->kw);
2951 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002952 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 goto out;
2954 }
2955 }
2956
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02002957 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
2958 if (expr->fetch->cap & SMP_CAP_L7)
2959 curproxy->acl_requires |= ACL_USE_L7_ANY;
2960
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 if (strcmp(args[myidx], "table") == 0) {
2962 myidx++;
2963 name = args[myidx++];
2964 }
2965
Willy Tarreauef6494c2010-01-28 17:12:36 +01002966 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002967 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2968 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2969 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002971 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 goto out;
2973 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002975 else if (*(args[myidx])) {
2976 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2977 file, linenum, args[0], args[myidx]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002979 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002980 goto out;
2981 }
Emeric Brun97679e72010-09-23 17:56:44 +02002982 if (flags & STK_ON_RSP)
2983 err_code |= warnif_cond_requires_req(cond, file, linenum);
2984 else
2985 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002986
Emeric Brunb982a3d2010-01-04 15:45:53 +01002987 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2988 rule->cond = cond;
2989 rule->expr = expr;
2990 rule->flags = flags;
2991 rule->table.name = name ? strdup(name) : NULL;
2992 LIST_INIT(&rule->list);
2993 if (flags & STK_ON_RSP)
2994 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2995 else
2996 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002999 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003000 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003001
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3003 curproxy->uri_auth = NULL; /* we must detach from the default config */
3004
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003005 if (!*args[1]) {
3006 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003007 } else if (!strcmp(args[1], "admin")) {
3008 struct stats_admin_rule *rule;
3009
3010 if (curproxy == &defproxy) {
3011 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
3014 }
3015
3016 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3017 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3018 err_code |= ERR_ALERT | ERR_ABORT;
3019 goto out;
3020 }
3021
3022 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3023 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3024 file, linenum, args[0], args[1]);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003028 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3029 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3030 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
3035 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3036
3037 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3038 rule->cond = cond;
3039 LIST_INIT(&rule->list);
3040 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 } else if (!strcmp(args[1], "uri")) {
3042 if (*(args[2]) == 0) {
3043 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3047 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 }
3051 } else if (!strcmp(args[1], "realm")) {
3052 if (*(args[2]) == 0) {
3053 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3057 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_ABORT;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003061 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003062 unsigned interval;
3063
3064 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3065 if (err) {
3066 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3067 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003070 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_ABORT;
3073 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003074 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003075 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003076 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003077
3078 if (curproxy == &defproxy) {
3079 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
3082 }
3083
3084 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3085 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3086 err_code |= ERR_ALERT | ERR_ABORT;
3087 goto out;
3088 }
3089
Willy Tarreauff011f22011-01-06 17:51:27 +01003090 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3091 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003092 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3093 file, linenum, args[0]);
3094 err_code |= ERR_WARN;
3095 }
3096
Willy Tarreauff011f22011-01-06 17:51:27 +01003097 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003098
Willy Tarreauff011f22011-01-06 17:51:27 +01003099 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
3102 }
3103
Willy Tarreauff011f22011-01-06 17:51:27 +01003104 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3105 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003106
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 } else if (!strcmp(args[1], "auth")) {
3108 if (*(args[2]) == 0) {
3109 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3113 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_ABORT;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
3117 } else if (!strcmp(args[1], "scope")) {
3118 if (*(args[2]) == 0) {
3119 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
3127 } else if (!strcmp(args[1], "enable")) {
3128 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3129 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_ABORT;
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003133 } else if (!strcmp(args[1], "hide-version")) {
3134 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_ABORT;
3137 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003138 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003139 } else if (!strcmp(args[1], "show-legends")) {
3140 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3141 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3142 err_code |= ERR_ALERT | ERR_ABORT;
3143 goto out;
3144 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003145 } else if (!strcmp(args[1], "show-node")) {
3146
3147 if (*args[2]) {
3148 int i;
3149 char c;
3150
3151 for (i=0; args[2][i]; i++) {
3152 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003153 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3154 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003155 break;
3156 }
3157
3158 if (!i || args[2][i]) {
3159 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3160 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3161 file, linenum, args[0], args[1]);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165 }
3166
3167 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3168 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172 } else if (!strcmp(args[1], "show-desc")) {
3173 char *desc = NULL;
3174
3175 if (*args[2]) {
3176 int i, len=0;
3177 char *d;
3178
3179 for(i=2; *args[i]; i++)
3180 len += strlen(args[i])+1;
3181
3182 desc = d = (char *)calloc(1, len);
3183
3184 d += sprintf(d, "%s", args[2]);
3185 for(i=3; *args[i]; i++)
3186 d += sprintf(d, " %s", args[i]);
3187 }
3188
3189 if (!*args[2] && !global.desc)
3190 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3191 file, linenum, args[1]);
3192 else {
3193 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3194 free(desc);
3195 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
3198 }
3199 free(desc);
3200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003202stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003203 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 +01003204 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 }
3209 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003210 int optnum;
3211
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003212 if (*(args[1]) == '\0') {
3213 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003218
3219 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3220 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003221 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3222 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3223 file, linenum, cfg_opts[optnum].name);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3228 err_code |= ERR_WARN;
3229 goto out;
3230 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003231
Willy Tarreau3842f002009-06-14 11:39:52 +02003232 curproxy->no_options &= ~cfg_opts[optnum].val;
3233 curproxy->options &= ~cfg_opts[optnum].val;
3234
3235 switch (kwm) {
3236 case KWM_STD:
3237 curproxy->options |= cfg_opts[optnum].val;
3238 break;
3239 case KWM_NO:
3240 curproxy->no_options |= cfg_opts[optnum].val;
3241 break;
3242 case KWM_DEF: /* already cleared */
3243 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003244 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245
Willy Tarreau93893792009-07-23 13:19:11 +02003246 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003247 }
3248 }
3249
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003250 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3251 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003252 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3253 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3254 file, linenum, cfg_opts2[optnum].name);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
Willy Tarreau93893792009-07-23 13:19:11 +02003258 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3259 err_code |= ERR_WARN;
3260 goto out;
3261 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003262
Willy Tarreau3842f002009-06-14 11:39:52 +02003263 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3264 curproxy->options2 &= ~cfg_opts2[optnum].val;
3265
3266 switch (kwm) {
3267 case KWM_STD:
3268 curproxy->options2 |= cfg_opts2[optnum].val;
3269 break;
3270 case KWM_NO:
3271 curproxy->no_options2 |= cfg_opts2[optnum].val;
3272 break;
3273 case KWM_DEF: /* already cleared */
3274 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003275 }
Willy Tarreau93893792009-07-23 13:19:11 +02003276 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003277 }
3278 }
3279
Willy Tarreau3842f002009-06-14 11:39:52 +02003280 if (kwm != KWM_STD) {
3281 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003282 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003285 }
3286
Emeric Brun3a058f32009-06-30 18:26:00 +02003287 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003288 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003290 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003291 if (*(args[2]) != '\0') {
3292 if (!strcmp(args[2], "clf")) {
3293 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003294 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003295 } else {
3296 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003299 }
3300 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003301 if (curproxy->logformat_string != default_http_log_format &&
3302 curproxy->logformat_string != default_tcp_log_format &&
3303 curproxy->logformat_string != clf_http_log_format)
3304 free(curproxy->logformat_string);
3305 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003306 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003307 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003309 if (curproxy->logformat_string != default_http_log_format &&
3310 curproxy->logformat_string != default_tcp_log_format &&
3311 curproxy->logformat_string != clf_http_log_format)
3312 free(curproxy->logformat_string);
3313 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 else if (!strcmp(args[1], "tcpka")) {
3316 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003317 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003319
3320 if (curproxy->cap & PR_CAP_FE)
3321 curproxy->options |= PR_O_TCP_CLI_KA;
3322 if (curproxy->cap & PR_CAP_BE)
3323 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
3325 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003326 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003327 err_code |= ERR_WARN;
3328
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003330 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003331 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003332 curproxy->options2 &= ~PR_O2_CHK_ANY;
3333 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 if (!*args[2]) { /* no argument */
3335 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3336 curproxy->check_len = strlen(DEF_CHECK_REQ);
3337 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003338 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003339 curproxy->check_req = (char *)malloc(reqlen);
3340 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003341 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003343 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 if (*args[4])
3345 reqlen += strlen(args[4]);
3346 else
3347 reqlen += strlen("HTTP/1.0");
3348
3349 curproxy->check_req = (char *)malloc(reqlen);
3350 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003351 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003353 }
3354 else if (!strcmp(args[1], "ssl-hello-chk")) {
3355 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003358
Willy Tarreaua534fea2008-08-03 12:19:50 +02003359 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003360 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003361 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003362 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
Willy Tarreau23677902007-05-08 23:50:35 +02003364 else if (!strcmp(args[1], "smtpchk")) {
3365 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003366 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003367 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003368 curproxy->options2 &= ~PR_O2_CHK_ANY;
3369 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003370
3371 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3372 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3373 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3374 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3375 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3376 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3377 curproxy->check_req = (char *)malloc(reqlen);
3378 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3379 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3380 } else {
3381 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3382 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3383 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3384 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3385 }
3386 }
3387 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003388 else if (!strcmp(args[1], "pgsql-check")) {
3389 /* use PostgreSQL request to check servers' health */
3390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3391 err_code |= ERR_WARN;
3392
3393 free(curproxy->check_req);
3394 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003395 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003396 curproxy->options2 |= PR_O2_PGSQL_CHK;
3397
3398 if (*(args[2])) {
3399 int cur_arg = 2;
3400
3401 while (*(args[cur_arg])) {
3402 if (strcmp(args[cur_arg], "user") == 0) {
3403 char * packet;
3404 uint32_t packet_len;
3405 uint32_t pv;
3406
3407 /* suboption header - needs additional argument for it */
3408 if (*(args[cur_arg+1]) == 0) {
3409 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3410 file, linenum, args[0], args[1], args[cur_arg]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414
3415 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3416 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3417 pv = htonl(0x30000); /* protocol version 3.0 */
3418
3419 packet = (char*) calloc(1, packet_len);
3420
3421 memcpy(packet + 4, &pv, 4);
3422
3423 /* copy "user" */
3424 memcpy(packet + 8, "user", 4);
3425
3426 /* copy username */
3427 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3428
3429 free(curproxy->check_req);
3430 curproxy->check_req = packet;
3431 curproxy->check_len = packet_len;
3432
3433 packet_len = htonl(packet_len);
3434 memcpy(packet, &packet_len, 4);
3435 cur_arg += 2;
3436 } else {
3437 /* unknown suboption - catchall */
3438 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3439 file, linenum, args[0], args[1]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443 } /* end while loop */
3444 }
3445 }
3446
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003447 else if (!strcmp(args[1], "redis-check")) {
3448 /* use REDIS PING request to check servers' health */
3449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3450 err_code |= ERR_WARN;
3451
3452 free(curproxy->check_req);
3453 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003454 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003455 curproxy->options2 |= PR_O2_REDIS_CHK;
3456
3457 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3458 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3459 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3460 }
3461
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003462 else if (!strcmp(args[1], "mysql-check")) {
3463 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003464 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3465 err_code |= ERR_WARN;
3466
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003467 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003468 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003469 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003470 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003471
3472 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3473 * const char mysql40_client_auth_pkt[] = {
3474 * "\x0e\x00\x00" // packet length
3475 * "\x01" // packet number
3476 * "\x00\x00" // client capabilities
3477 * "\x00\x00\x01" // max packet
3478 * "haproxy\x00" // username (null terminated string)
3479 * "\x00" // filler (always 0x00)
3480 * "\x01\x00\x00" // packet length
3481 * "\x00" // packet number
3482 * "\x01" // COM_QUIT command
3483 * };
3484 */
3485
3486 if (*(args[2])) {
3487 int cur_arg = 2;
3488
3489 while (*(args[cur_arg])) {
3490 if (strcmp(args[cur_arg], "user") == 0) {
3491 char *mysqluser;
3492 int packetlen, reqlen, userlen;
3493
3494 /* suboption header - needs additional argument for it */
3495 if (*(args[cur_arg+1]) == 0) {
3496 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3497 file, linenum, args[0], args[1], args[cur_arg]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501 mysqluser = args[cur_arg + 1];
3502 userlen = strlen(mysqluser);
3503 packetlen = userlen + 7;
3504 reqlen = packetlen + 9;
3505
3506 free(curproxy->check_req);
3507 curproxy->check_req = (char *)calloc(1, reqlen);
3508 curproxy->check_len = reqlen;
3509
3510 snprintf(curproxy->check_req, 4, "%c%c%c",
3511 ((unsigned char) packetlen & 0xff),
3512 ((unsigned char) (packetlen >> 8) & 0xff),
3513 ((unsigned char) (packetlen >> 16) & 0xff));
3514
3515 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003516 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003517 curproxy->check_req[8] = 1;
3518 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3519 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3520 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3521 cur_arg += 2;
3522 } else {
3523 /* unknown suboption - catchall */
3524 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3525 file, linenum, args[0], args[1]);
3526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
3528 }
3529 } /* end while loop */
3530 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003531 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003532 else if (!strcmp(args[1], "ldap-check")) {
3533 /* use LDAP request to check servers' health */
3534 free(curproxy->check_req);
3535 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003536 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003537 curproxy->options2 |= PR_O2_LDAP_CHK;
3538
3539 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3540 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3541 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3542 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003543 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003544 int cur_arg;
3545
3546 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3547 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003548 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003549
Willy Tarreau87cf5142011-08-19 22:57:24 +02003550 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003551
3552 free(curproxy->fwdfor_hdr_name);
3553 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3554 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3555
3556 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3557 cur_arg = 2;
3558 while (*(args[cur_arg])) {
3559 if (!strcmp(args[cur_arg], "except")) {
3560 /* suboption except - needs additional argument for it */
3561 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3562 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3563 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003566 }
3567 /* flush useless bits */
3568 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003569 cur_arg += 2;
3570 } else if (!strcmp(args[cur_arg], "header")) {
3571 /* suboption header - needs additional argument for it */
3572 if (*(args[cur_arg+1]) == 0) {
3573 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3574 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003577 }
3578 free(curproxy->fwdfor_hdr_name);
3579 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3580 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3581 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003582 } else if (!strcmp(args[cur_arg], "if-none")) {
3583 curproxy->options &= ~PR_O_FF_ALWAYS;
3584 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003585 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003586 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003587 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003588 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003591 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003592 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003593 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003594 else if (!strcmp(args[1], "originalto")) {
3595 int cur_arg;
3596
3597 /* insert x-original-to field, but not for the IP address listed as an except.
3598 * set default options (ie: bitfield, header name, etc)
3599 */
3600
3601 curproxy->options |= PR_O_ORGTO;
3602
3603 free(curproxy->orgto_hdr_name);
3604 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3605 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3606
Willy Tarreau87cf5142011-08-19 22:57:24 +02003607 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003608 cur_arg = 2;
3609 while (*(args[cur_arg])) {
3610 if (!strcmp(args[cur_arg], "except")) {
3611 /* suboption except - needs additional argument for it */
3612 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3613 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3614 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003617 }
3618 /* flush useless bits */
3619 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3620 cur_arg += 2;
3621 } else if (!strcmp(args[cur_arg], "header")) {
3622 /* suboption header - needs additional argument for it */
3623 if (*(args[cur_arg+1]) == 0) {
3624 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3625 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003628 }
3629 free(curproxy->orgto_hdr_name);
3630 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3631 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3632 cur_arg += 2;
3633 } else {
3634 /* unknown suboption - catchall */
3635 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3636 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003639 }
3640 } /* end while loop */
3641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 else {
3643 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 }
Willy Tarreau93893792009-07-23 13:19:11 +02003647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003648 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003649 else if (!strcmp(args[0], "default_backend")) {
3650 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003652
3653 if (*(args[1]) == 0) {
3654 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003657 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003658 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003659 curproxy->defbe.name = strdup(args[1]);
3660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003662 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003664
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003665 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3666 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 /* enable reconnections to dispatch */
3669 curproxy->options |= PR_O_REDISP;
3670 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003671 else if (!strcmp(args[0], "http-check")) {
3672 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003674
3675 if (strcmp(args[1], "disable-on-404") == 0) {
3676 /* enable a graceful server shutdown on an HTTP 404 response */
3677 curproxy->options |= PR_O_DISABLE404;
3678 }
Willy Tarreauef781042010-01-27 11:53:01 +01003679 else if (strcmp(args[1], "send-state") == 0) {
3680 /* enable emission of the apparent state of a server in HTTP checks */
3681 curproxy->options2 |= PR_O2_CHK_SNDST;
3682 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003683 else if (strcmp(args[1], "expect") == 0) {
3684 const char *ptr_arg;
3685 int cur_arg;
3686
3687 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3688 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692
3693 cur_arg = 2;
3694 /* consider exclamation marks, sole or at the beginning of a word */
3695 while (*(ptr_arg = args[cur_arg])) {
3696 while (*ptr_arg == '!') {
3697 curproxy->options2 ^= PR_O2_EXP_INV;
3698 ptr_arg++;
3699 }
3700 if (*ptr_arg)
3701 break;
3702 cur_arg++;
3703 }
3704 /* now ptr_arg points to the beginning of a word past any possible
3705 * exclamation mark, and cur_arg is the argument which holds this word.
3706 */
3707 if (strcmp(ptr_arg, "status") == 0) {
3708 if (!*(args[cur_arg + 1])) {
3709 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3710 file, linenum, args[0], args[1], ptr_arg);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
3714 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003715 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003716 curproxy->expect_str = strdup(args[cur_arg + 1]);
3717 }
3718 else if (strcmp(ptr_arg, "string") == 0) {
3719 if (!*(args[cur_arg + 1])) {
3720 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3721 file, linenum, args[0], args[1], ptr_arg);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
3725 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003726 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003727 curproxy->expect_str = strdup(args[cur_arg + 1]);
3728 }
3729 else if (strcmp(ptr_arg, "rstatus") == 0) {
3730 if (!*(args[cur_arg + 1])) {
3731 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3732 file, linenum, args[0], args[1], ptr_arg);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003737 free(curproxy->expect_str);
3738 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3739 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003740 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3741 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3742 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3743 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
3746 }
3747 }
3748 else if (strcmp(ptr_arg, "rstring") == 0) {
3749 if (!*(args[cur_arg + 1])) {
3750 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3751 file, linenum, args[0], args[1], ptr_arg);
3752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
3754 }
3755 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003756 free(curproxy->expect_str);
3757 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3758 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003759 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3760 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3761 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3762 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
3765 }
3766 }
3767 else {
3768 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3769 file, linenum, args[0], args[1], ptr_arg);
3770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
3772 }
3773 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003774 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003775 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 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003778 }
3779 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003780 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003781 if (curproxy == &defproxy) {
3782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_ALERT | ERR_FATAL;
3784 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003785 }
3786
Willy Tarreaub80c2302007-11-30 20:51:32 +01003787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003789
3790 if (strcmp(args[1], "fail") == 0) {
3791 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003792 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003793 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3794 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003797 }
3798
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003799 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3800 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3801 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003804 }
3805 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3806 }
3807 else {
3808 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003811 }
3812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813#ifdef TPROXY
3814 else if (!strcmp(args[0], "transparent")) {
3815 /* enable transparent proxy connections */
3816 curproxy->options |= PR_O_TRANSP;
3817 }
3818#endif
3819 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003820 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003822
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 if (*(args[1]) == 0) {
3824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828 curproxy->maxconn = atol(args[1]);
3829 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003830 else if (!strcmp(args[0], "backlog")) { /* backlog */
3831 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003833
3834 if (*(args[1]) == 0) {
3835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003838 }
3839 curproxy->backlog = atol(args[1]);
3840 }
Willy Tarreau86034312006-12-29 00:10:33 +01003841 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003844
Willy Tarreau86034312006-12-29 00:10:33 +01003845 if (*(args[1]) == 0) {
3846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003849 }
3850 curproxy->fullconn = atol(args[1]);
3851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3853 if (*(args[1]) == 0) {
3854 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003858 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3859 if (err) {
3860 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3861 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003864 }
3865 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 }
3867 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003868 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 if (curproxy == &defproxy) {
3870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003874 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003876
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 if (strchr(args[1], ':') == NULL) {
3878 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003882 sk = str2sa(args[1]);
3883 if (!sk) {
3884 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003889 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
3891 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003892 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003894
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003895 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3896 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003901 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3903 err_code |= ERR_WARN;
3904
3905 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3906 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3907 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3908 }
3909 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3910 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3911 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3912 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003913 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3914 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3915 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3916 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003917 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003918 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003923 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003925 char *rport, *raddr;
3926 short realport = 0;
3927 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003934 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936
3937 if (!*args[2]) {
3938 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003943
3944 err = invalid_char(args[1]);
3945 if (err) {
3946 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3947 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003950 }
3951
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003953 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003954
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003955 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3956 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3957 err_code |= ERR_ALERT | ERR_ABORT;
3958 goto out;
3959 }
3960
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961 /* the servers are linked backwards first */
3962 newsrv->next = curproxy->srv;
3963 curproxy->srv = newsrv;
3964 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003965 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003966 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967
Simon Hormanaf514952011-06-21 14:34:57 +09003968 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003969 LIST_INIT(&newsrv->pendconns);
3970 do_check = 0;
3971 newsrv->state = SRV_RUNNING; /* early server setup */
3972 newsrv->last_change = now.tv_sec;
3973 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003975 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003976 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977 * - IP: => port=+0, relative
3978 * - IP:N => port=N, absolute
3979 * - IP:+N => port=+N, relative
3980 * - IP:-N => port=-N, relative
3981 */
3982 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003983 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 if (rport) {
3985 *rport++ = 0;
3986 realport = atol(rport);
3987 if (!isdigit((unsigned char)*rport))
3988 newsrv->state |= SRV_MAPPORTS;
3989 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003991
Willy Tarreaufab5a432011-03-04 15:31:53 +01003992 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003993 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003994 if (!sk) {
3995 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
3999 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004000 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4001 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004002
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004003 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004004 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4005 file, linenum, newsrv->addr.ss_family, args[2]);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004009 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004010
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004011 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004012 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004013 newsrv->inter = curproxy->defsrv.inter;
4014 newsrv->fastinter = curproxy->defsrv.fastinter;
4015 newsrv->downinter = curproxy->defsrv.downinter;
4016 newsrv->rise = curproxy->defsrv.rise;
4017 newsrv->fall = curproxy->defsrv.fall;
4018 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4019 newsrv->minconn = curproxy->defsrv.minconn;
4020 newsrv->maxconn = curproxy->defsrv.maxconn;
4021 newsrv->slowstart = curproxy->defsrv.slowstart;
4022 newsrv->onerror = curproxy->defsrv.onerror;
4023 newsrv->consecutive_errors_limit
4024 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004025#ifdef OPENSSL
4026 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4027#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004028 newsrv->uweight = newsrv->iweight
4029 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004033 cur_arg = 3;
4034 } else {
4035 newsrv = &curproxy->defsrv;
4036 cur_arg = 1;
4037 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004040 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 newsrv->cookie = strdup(args[cur_arg + 1]);
4042 newsrv->cklen = strlen(args[cur_arg + 1]);
4043 cur_arg += 2;
4044 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004046 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4047 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4048 cur_arg += 2;
4049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004051 if (!*args[cur_arg + 1]) {
4052 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4053 file, linenum, args[cur_arg]);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056 }
4057
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004059 if (newsrv->rise <= 0) {
4060 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4061 file, linenum, args[cur_arg]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
Willy Tarreau96839092010-03-29 10:02:24 +02004066 if (newsrv->health)
4067 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 cur_arg += 2;
4069 }
4070 else if (!strcmp(args[cur_arg], "fall")) {
4071 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004072
4073 if (!*args[cur_arg + 1]) {
4074 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4075 file, linenum, args[cur_arg]);
4076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
4078 }
4079
4080 if (newsrv->fall <= 0) {
4081 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4082 file, linenum, args[cur_arg]);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
4086
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 cur_arg += 2;
4088 }
4089 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004090 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4091 if (err) {
4092 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4093 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004096 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004097 if (val <= 0) {
4098 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4099 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004102 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004103 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 cur_arg += 2;
4105 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004106 else if (!strcmp(args[cur_arg], "fastinter")) {
4107 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4108 if (err) {
4109 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4110 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004113 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004114 if (val <= 0) {
4115 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4116 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004119 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004120 newsrv->fastinter = val;
4121 cur_arg += 2;
4122 }
4123 else if (!strcmp(args[cur_arg], "downinter")) {
4124 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4125 if (err) {
4126 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4127 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004130 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004131 if (val <= 0) {
4132 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4133 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004136 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004137 newsrv->downinter = val;
4138 cur_arg += 2;
4139 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004141 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004142 if (!sk) {
4143 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004147 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004148 cur_arg += 2;
4149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004151 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 cur_arg += 2;
4153 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004154 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 newsrv->state |= SRV_BACKUP;
4156 cur_arg ++;
4157 }
Simon Hormanfa461682011-06-25 09:39:49 +09004158 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4159 newsrv->state |= SRV_NON_STICK;
4160 cur_arg ++;
4161 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004162 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4163 newsrv->state |= SRV_SEND_PROXY;
4164 cur_arg ++;
4165 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004166 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4167 newsrv->check.send_proxy = 1;
4168 cur_arg ++;
4169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 else if (!strcmp(args[cur_arg], "weight")) {
4171 int w;
4172 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004173 if (w < 0 || w > 256) {
4174 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004175 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004179 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 cur_arg += 2;
4181 }
4182 else if (!strcmp(args[cur_arg], "minconn")) {
4183 newsrv->minconn = atol(args[cur_arg + 1]);
4184 cur_arg += 2;
4185 }
4186 else if (!strcmp(args[cur_arg], "maxconn")) {
4187 newsrv->maxconn = atol(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004190 else if (!strcmp(args[cur_arg], "maxqueue")) {
4191 newsrv->maxqueue = atol(args[cur_arg + 1]);
4192 cur_arg += 2;
4193 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004194 else if (!strcmp(args[cur_arg], "slowstart")) {
4195 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004196 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004197 if (err) {
4198 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4199 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004202 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004203 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004204 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4205 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004208 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004209 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004210 cur_arg += 2;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004213
4214 if (!*args[cur_arg + 1]) {
4215 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004219 }
4220
4221 newsrv->trackit = strdup(args[cur_arg + 1]);
4222
4223 cur_arg += 2;
4224 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004225 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 global.maxsock++;
4227 do_check = 1;
4228 cur_arg += 1;
4229 }
Willy Tarreau96839092010-03-29 10:02:24 +02004230 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4231 newsrv->state |= SRV_MAINTAIN;
4232 newsrv->state &= ~SRV_RUNNING;
4233 newsrv->health = 0;
4234 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004235 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004236 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004237 if (!strcmp(args[cur_arg + 1], "none"))
4238 newsrv->observe = HANA_OBS_NONE;
4239 else if (!strcmp(args[cur_arg + 1], "layer4"))
4240 newsrv->observe = HANA_OBS_LAYER4;
4241 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4242 if (curproxy->mode != PR_MODE_HTTP) {
4243 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4244 file, linenum, args[cur_arg + 1]);
4245 err_code |= ERR_ALERT;
4246 }
4247 newsrv->observe = HANA_OBS_LAYER7;
4248 }
4249 else {
4250 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004251 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004252 file, linenum, args[cur_arg], args[cur_arg + 1]);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256
4257 cur_arg += 2;
4258 }
4259 else if (!strcmp(args[cur_arg], "on-error")) {
4260 if (!strcmp(args[cur_arg + 1], "fastinter"))
4261 newsrv->onerror = HANA_ONERR_FASTINTER;
4262 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4263 newsrv->onerror = HANA_ONERR_FAILCHK;
4264 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4265 newsrv->onerror = HANA_ONERR_SUDDTH;
4266 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4267 newsrv->onerror = HANA_ONERR_MARKDWN;
4268 else {
4269 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004270 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004271 file, linenum, args[cur_arg], args[cur_arg + 1]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 cur_arg += 2;
4277 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004278 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4279 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4280 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4281 else {
4282 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4283 file, linenum, args[cur_arg], args[cur_arg + 1]);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287
4288 cur_arg += 2;
4289 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004290 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4291 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4292 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4293 else {
4294 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4295 file, linenum, args[cur_arg], args[cur_arg + 1]);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299
4300 cur_arg += 2;
4301 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004302 else if (!strcmp(args[cur_arg], "error-limit")) {
4303 if (!*args[cur_arg + 1]) {
4304 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4305 file, linenum, args[cur_arg]);
4306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
4309
4310 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4311
4312 if (newsrv->consecutive_errors_limit <= 0) {
4313 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4314 file, linenum, args[cur_arg]);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004318 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004319 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004320 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004321 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004322 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004323
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004325#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004326 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004327 file, linenum, "source", "usesrc");
4328#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004329 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004331#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004334 }
4335 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004336 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4337 if (!sk) {
4338 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
4341 }
4342 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004343
4344 if (port_low != port_high) {
4345 int i;
4346 if (port_low <= 0 || port_low > 65535 ||
4347 port_high <= 0 || port_high > 65535 ||
4348 port_low > port_high) {
4349 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4350 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004353 }
4354 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4355 for (i = 0; i < newsrv->sport_range->size; i++)
4356 newsrv->sport_range->ports[i] = port_low + i;
4357 }
4358
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004360 while (*(args[cur_arg])) {
4361 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004362#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4363#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004364 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4365 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4366 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004369 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004370#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004371 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004372 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004373 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376 }
4377 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004378 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004379 newsrv->state |= SRV_TPROXY_CLI;
4380 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004381 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004382 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004383 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4384 char *name, *end;
4385
4386 name = args[cur_arg+1] + 7;
4387 while (isspace(*name))
4388 name++;
4389
4390 end = name;
4391 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4392 end++;
4393
4394 newsrv->state &= ~SRV_TPROXY_MASK;
4395 newsrv->state |= SRV_TPROXY_DYN;
4396 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4397 newsrv->bind_hdr_len = end - name;
4398 memcpy(newsrv->bind_hdr_name, name, end - name);
4399 newsrv->bind_hdr_name[end-name] = '\0';
4400 newsrv->bind_hdr_occ = -1;
4401
4402 /* now look for an occurrence number */
4403 while (isspace(*end))
4404 end++;
4405 if (*end == ',') {
4406 end++;
4407 name = end;
4408 if (*end == '-')
4409 end++;
4410 while (isdigit(*end))
4411 end++;
4412 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4413 }
4414
4415 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4416 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4417 " occurrences values smaller than %d.\n",
4418 file, linenum, MAX_HDR_HISTORY);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004423 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004424 if (!sk) {
4425 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004431 }
4432 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004433#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004434 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004435#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004436 cur_arg += 2;
4437 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004438#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004439 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004440 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004441 err_code |= ERR_ALERT | ERR_FATAL;
4442 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4444 } /* "usesrc" */
4445
4446 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4447#ifdef SO_BINDTODEVICE
4448 if (!*args[cur_arg + 1]) {
4449 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004453 }
4454 if (newsrv->iface_name)
4455 free(newsrv->iface_name);
4456
4457 newsrv->iface_name = strdup(args[cur_arg + 1]);
4458 newsrv->iface_len = strlen(newsrv->iface_name);
4459 global.last_checks |= LSTCHK_NETADM;
4460#else
4461 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4462 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004465#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004466 cur_arg += 2;
4467 continue;
4468 }
4469 /* this keyword in not an option of "source" */
4470 break;
4471 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004473 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004474 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4475 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004478 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004480 static int srv_dumped;
4481 struct srv_kw *kw;
4482 char *err;
4483
4484 kw = srv_find_kw(args[cur_arg]);
4485 if (kw) {
4486 char *err = NULL;
4487 int code;
4488
4489 if (!kw->parse) {
4490 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4491 file, linenum, args[0], args[1], args[cur_arg]);
4492 cur_arg += 1 + kw->skip ;
4493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
4496
4497 if (defsrv && !kw->default_ok) {
4498 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4499 file, linenum, args[0], args[1], args[cur_arg]);
4500 cur_arg += 1 + kw->skip ;
4501 err_code |= ERR_ALERT;
4502 continue;
4503 }
4504
4505 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4506 err_code |= code;
4507
4508 if (code) {
4509 if (err && *err) {
4510 indent_msg(&err, 2);
4511 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4512 }
4513 else
4514 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4515 file, linenum, args[0], args[1], args[cur_arg]);
4516 if (code & ERR_FATAL) {
4517 free(err);
4518 cur_arg += 1 + kw->skip;
4519 goto out;
4520 }
4521 }
4522 free(err);
4523 cur_arg += 1 + kw->skip;
4524 continue;
4525 }
4526
4527 err = NULL;
4528 if (!srv_dumped) {
4529 srv_dump_kws(&err);
4530 indent_msg(&err, 4);
4531 srv_dumped = 1;
4532 }
4533
4534 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4535 file, linenum, args[0], args[1], args[cur_arg],
4536 err ? " Registered keywords :" : "", err ? err : "");
4537 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004538
Willy Tarreau93893792009-07-23 13:19:11 +02004539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 }
4542 }
4543
4544 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004545 if (newsrv->trackit) {
4546 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4547 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004550 }
4551
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004552 /* If neither a port nor an addr was specified and no check transport
4553 * layer is forced, then the transport layer used by the checks is the
4554 * same as for the production traffic. Otherwise we use raw_sock by
4555 * default, unless one is specified.
4556 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004557 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004558#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004559 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004560#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004561 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4562 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004563 /* try to get the port from check.addr if check.port not set */
4564 if (!newsrv->check.port)
4565 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004566
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004567 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4568 newsrv->check.port = realport; /* by default */
4569 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004570 /* not yet valid, because no port was set on
4571 * the server either. We'll check if we have
4572 * a known port on the first listener.
4573 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004574 struct listener *l;
4575
4576 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004577 newsrv->check.port = get_host_port(&l->addr);
4578 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004579 break;
4580 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004581 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004582 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4584 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004588
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004589 /* Allocate buffer for check requests... */
4590 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004591 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4592 err_code |= ERR_ALERT | ERR_ABORT;
4593 goto out;
4594 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004595 newsrv->check.bi->size = global.tune.chksize;
4596
4597 /* Allocate buffer for check responses... */
4598 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4599 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4600 err_code |= ERR_ALERT | ERR_ABORT;
4601 goto out;
4602 }
4603 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004604
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004605 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004606 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004607 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4608 err_code |= ERR_ALERT | ERR_ABORT;
4609 goto out;
4610 }
4611
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004612 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4613 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614 newsrv->state |= SRV_CHECKED;
4615 }
4616
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004617 if (!defsrv) {
4618 if (newsrv->state & SRV_BACKUP)
4619 curproxy->srv_bck++;
4620 else
4621 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004622
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004623 newsrv->prev_state = newsrv->state;
4624 }
William Lallemanda73203e2012-03-12 12:48:57 +01004625 }
4626
4627 else if (strcmp(args[0], "unique-id-format") == 0) {
4628 if (!*(args[1])) {
4629 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004633 free(curproxy->uniqueid_format_string);
4634 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004635 }
William Lallemanda73203e2012-03-12 12:48:57 +01004636
4637 else if (strcmp(args[0], "unique-id-header") == 0) {
4638 if (!*(args[1])) {
4639 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
4643 free(curproxy->header_unique_id);
4644 curproxy->header_unique_id = strdup(args[1]);
4645 }
4646
William Lallemand723b73a2012-02-08 16:37:49 +01004647 else if (strcmp(args[0], "log-format") == 0) {
4648 if (!*(args[1])) {
4649 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004653
4654 if (curproxy->logformat_string != default_http_log_format &&
4655 curproxy->logformat_string != default_tcp_log_format &&
4656 curproxy->logformat_string != clf_http_log_format)
4657 free(curproxy->logformat_string);
4658 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
William Lallemand723b73a2012-02-08 16:37:49 +01004660
William Lallemand0f99e342011-10-12 17:50:54 +02004661 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4662 /* delete previous herited or defined syslog servers */
4663 struct logsrv *back;
4664
4665 if (*(args[1]) != 0) {
4666 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670
William Lallemand723b73a2012-02-08 16:37:49 +01004671 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4672 LIST_DEL(&tmplogsrv->list);
4673 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004674 }
4675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004677 struct logsrv *logsrv;
4678
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004680 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004681 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004682 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004683 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004684 LIST_INIT(&node->list);
4685 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004689
4690 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004691
William Lallemand0f99e342011-10-12 17:50:54 +02004692 logsrv->facility = get_log_facility(args[2]);
4693 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 }
4699
William Lallemand0f99e342011-10-12 17:50:54 +02004700 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->level = get_log_level(args[3]);
4703 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 }
4710
William Lallemand0f99e342011-10-12 17:50:54 +02004711 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004712 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004713 logsrv->minlvl = get_log_level(args[4]);
4714 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004715 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
4718
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004719 }
4720 }
4721
Robert Tsai81ae1952007-12-05 10:47:29 +01004722 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004723 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004724 if (!sk) {
4725 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004726 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
William Lallemand0f99e342011-10-12 17:50:54 +02004730 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004731 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004732 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004733 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004734 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 }
William Lallemand0f99e342011-10-12 17:50:54 +02004738 logsrv->addr = *sk;
4739 if (!get_host_port(&logsrv->addr))
4740 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
William Lallemand0f99e342011-10-12 17:50:54 +02004742
4743 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
4745 else {
4746 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4747 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 }
4752 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004753 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004754 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004755
Willy Tarreau977b8e42006-12-29 14:19:17 +01004756 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004757 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004758
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4761 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004765
4766 /* we must first clear any optional default setting */
4767 curproxy->options &= ~PR_O_TPXY_MASK;
4768 free(curproxy->iface_name);
4769 curproxy->iface_name = NULL;
4770 curproxy->iface_len = 0;
4771
Willy Tarreaud5191e72010-02-09 20:50:45 +01004772 sk = str2sa(args[1]);
4773 if (!sk) {
4774 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
4778 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004780
4781 cur_arg = 2;
4782 while (*(args[cur_arg])) {
4783 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004784#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4785#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004786 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4787 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4788 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004791 }
4792#endif
4793 if (!*args[cur_arg + 1]) {
4794 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4795 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798 }
4799
4800 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004801 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004802 curproxy->options |= PR_O_TPXY_CLI;
4803 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004804 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004805 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004806 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4807 char *name, *end;
4808
4809 name = args[cur_arg+1] + 7;
4810 while (isspace(*name))
4811 name++;
4812
4813 end = name;
4814 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4815 end++;
4816
4817 curproxy->options &= ~PR_O_TPXY_MASK;
4818 curproxy->options |= PR_O_TPXY_DYN;
4819 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4820 curproxy->bind_hdr_len = end - name;
4821 memcpy(curproxy->bind_hdr_name, name, end - name);
4822 curproxy->bind_hdr_name[end-name] = '\0';
4823 curproxy->bind_hdr_occ = -1;
4824
4825 /* now look for an occurrence number */
4826 while (isspace(*end))
4827 end++;
4828 if (*end == ',') {
4829 end++;
4830 name = end;
4831 if (*end == '-')
4832 end++;
4833 while (isdigit(*end))
4834 end++;
4835 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4836 }
4837
4838 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4839 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4840 " occurrences values smaller than %d.\n",
4841 file, linenum, MAX_HDR_HISTORY);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004845 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004846 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004847 if (!sk) {
4848 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
4851 }
4852 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004854 }
4855 global.last_checks |= LSTCHK_NETADM;
4856#if !defined(CONFIG_HAP_LINUX_TPROXY)
4857 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004858#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004859#else /* no TPROXY support */
4860 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004861 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004864#endif
4865 cur_arg += 2;
4866 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004867 }
4868
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004869 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4870#ifdef SO_BINDTODEVICE
4871 if (!*args[cur_arg + 1]) {
4872 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4873 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004876 }
4877 if (curproxy->iface_name)
4878 free(curproxy->iface_name);
4879
4880 curproxy->iface_name = strdup(args[cur_arg + 1]);
4881 curproxy->iface_len = strlen(curproxy->iface_name);
4882 global.last_checks |= LSTCHK_NETADM;
4883#else
4884 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4885 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004888#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 cur_arg += 2;
4890 continue;
4891 }
4892 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004893 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004898 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4899 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4900 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911
4912 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004913 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004914 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004920 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004921 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
4925 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004927 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004928 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004941 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004946 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004952 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004953 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004959 }
4960 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4970 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974
4975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004990 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004991 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005004 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005005 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005009 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005017 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005018
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 if (curproxy == &defproxy) {
5020 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005024 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 if (*(args[1]) == 0) {
5028 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005032
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005033 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005034 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5035 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5036 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039 }
5040 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5041 }
5042 else if (*args[2]) {
5043 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5044 file, linenum, args[0], args[2]);
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
5048
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005049 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005050 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005051 wl->s = strdup(args[1]);
5052 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005053 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
5055 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005062
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005064 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005065 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
5069 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005071 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005072 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
5076 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005078 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005079 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5086 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
5090
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005092 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005093 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
5097 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005099 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005100 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
5111 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005112 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005113
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 if (curproxy == &defproxy) {
5115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005119 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 if (*(args[1]) == 0) {
5123 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005126 }
5127
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005128 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005129 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5130 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5131 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
5134 }
5135 err_code |= warnif_cond_requires_req(cond, file, linenum);
5136 }
5137 else if (*args[2]) {
5138 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5139 file, linenum, args[0], args[2]);
5140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
5142 }
5143
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005144 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005145 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005146 wl->s = strdup(args[1]);
5147 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
5149 else if (!strcmp(args[0], "errorloc") ||
5150 !strcmp(args[0], "errorloc302") ||
5151 !strcmp(args[0], "errorloc303")) { /* error location */
5152 int errnum, errlen;
5153 char *err;
5154
Willy Tarreau977b8e42006-12-29 14:19:17 +01005155 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005157
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005159 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 }
5163
5164 errnum = atol(args[1]);
5165 if (!strcmp(args[0], "errorloc303")) {
5166 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5167 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5168 } else {
5169 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5170 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5171 }
5172
Willy Tarreau0f772532006-12-23 20:51:41 +01005173 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5174 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005175 chunk_destroy(&curproxy->errmsg[rc]);
5176 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005177 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005180
5181 if (rc >= HTTP_ERR_SIZE) {
5182 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5183 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 free(err);
5185 }
5186 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5188 int errnum, errlen, fd;
5189 char *err;
5190 struct stat stat;
5191
5192 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005194
5195 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005196 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005199 }
5200
5201 fd = open(args[2], O_RDONLY);
5202 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5203 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5204 file, linenum, args[2], args[1]);
5205 if (fd >= 0)
5206 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 }
5210
Willy Tarreau27a674e2009-08-17 07:23:33 +02005211 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005212 errlen = stat.st_size;
5213 } else {
5214 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005215 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005217 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005218 }
5219
5220 err = malloc(errlen); /* malloc() must succeed during parsing */
5221 errnum = read(fd, err, errlen);
5222 if (errnum != errlen) {
5223 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5224 file, linenum, args[2], args[1]);
5225 close(fd);
5226 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005229 }
5230 close(fd);
5231
5232 errnum = atol(args[1]);
5233 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5234 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005235 chunk_destroy(&curproxy->errmsg[rc]);
5236 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005237 break;
5238 }
5239 }
5240
5241 if (rc >= HTTP_ERR_SIZE) {
5242 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5243 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005245 free(err);
5246 }
5247 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005248 else if (!strcmp(args[0], "compression")) {
5249 struct comp *comp;
5250 if (curproxy->comp == NULL) {
5251 comp = calloc(1, sizeof(struct comp));
5252 curproxy->comp = comp;
5253 } else {
5254 comp = curproxy->comp;
5255 }
5256
5257 if (!strcmp(args[1], "algo")) {
5258 int cur_arg;
5259 cur_arg = 2;
5260 if (!*args[cur_arg]) {
5261 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5262 file, linenum, args[0]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266 while (*(args[cur_arg])) {
5267 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5268 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5269 file, linenum, args[0], args[cur_arg]);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
5273 cur_arg ++;
5274 continue;
5275 }
5276 }
5277 else if (!strcmp(args[1], "type")) {
5278 int cur_arg;
5279 cur_arg = 2;
5280 if (!*args[cur_arg]) {
5281 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5282 file, linenum, args[0]);
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 goto out;
5285 }
5286 while (*(args[cur_arg])) {
5287 comp_append_type(comp, args[cur_arg]);
5288 cur_arg ++;
5289 continue;
5290 }
5291 }
5292 else {
5293 Alert("parsing [%s:%d] : '%s' expects algo or type\n",
5294 file, linenum, args[0]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005300 struct cfg_kw_list *kwl;
5301 int index;
5302
5303 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5304 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5305 if (kwl->kw[index].section != CFG_LISTEN)
5306 continue;
5307 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5308 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005309 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005310 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005311 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005312 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005313 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
5315 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005316 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005317 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005318 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005319 err_code |= ERR_WARN;
5320 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005321 }
Willy Tarreau93893792009-07-23 13:19:11 +02005322 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005323 }
5324 }
5325 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005326
Willy Tarreau6daf3432008-01-22 16:44:08 +01005327 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreau93893792009-07-23 13:19:11 +02005331 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005332 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005333 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334}
5335
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005336int
5337cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5338{
5339
5340 int err_code = 0;
5341 const char *err;
5342
5343 if (!strcmp(args[0], "userlist")) { /* new userlist */
5344 struct userlist *newul;
5345
5346 if (!*args[1]) {
5347 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5348 file, linenum, args[0]);
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352
5353 err = invalid_char(args[1]);
5354 if (err) {
5355 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5356 file, linenum, *err, args[0], args[1]);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360
5361 for (newul = userlist; newul; newul = newul->next)
5362 if (!strcmp(newul->name, args[1])) {
5363 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5364 file, linenum, args[1]);
5365 err_code |= ERR_WARN;
5366 goto out;
5367 }
5368
5369 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5370 if (!newul) {
5371 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5372 err_code |= ERR_ALERT | ERR_ABORT;
5373 goto out;
5374 }
5375
5376 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5377 newul->name = strdup(args[1]);
5378
5379 if (!newul->groupusers | !newul->name) {
5380 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5381 err_code |= ERR_ALERT | ERR_ABORT;
5382 goto out;
5383 }
5384
5385 newul->next = userlist;
5386 userlist = newul;
5387
5388 } else if (!strcmp(args[0], "group")) { /* new group */
5389 int cur_arg, i;
5390 const char *err;
5391
5392 if (!*args[1]) {
5393 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5394 file, linenum, args[0]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
5399 err = invalid_char(args[1]);
5400 if (err) {
5401 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5402 file, linenum, *err, args[0], args[1]);
5403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
5406
5407 for(i = 0; i < userlist->grpcnt; i++)
5408 if (!strcmp(userlist->groups[i], args[1])) {
5409 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5410 file, linenum, args[1], userlist->name);
5411 err_code |= ERR_ALERT;
5412 goto out;
5413 }
5414
5415 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5416 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5417 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
5420 }
5421
5422 cur_arg = 2;
5423
5424 while (*args[cur_arg]) {
5425 if (!strcmp(args[cur_arg], "users")) {
5426 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5427 cur_arg += 2;
5428 continue;
5429 } else {
5430 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5431 file, linenum, args[0]);
5432 err_code |= ERR_ALERT | ERR_FATAL;
5433 goto out;
5434 }
5435 }
5436
5437 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5438 } else if (!strcmp(args[0], "user")) { /* new user */
5439 struct auth_users *newuser;
5440 int cur_arg;
5441
5442 if (!*args[1]) {
5443 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5444 file, linenum, args[0]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
5448
5449 for (newuser = userlist->users; newuser; newuser = newuser->next)
5450 if (!strcmp(newuser->user, args[1])) {
5451 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5452 file, linenum, args[1], userlist->name);
5453 err_code |= ERR_ALERT;
5454 goto out;
5455 }
5456
5457 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5458 if (!newuser) {
5459 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5460 err_code |= ERR_ALERT | ERR_ABORT;
5461 goto out;
5462 }
5463
5464 newuser->user = strdup(args[1]);
5465
5466 newuser->next = userlist->users;
5467 userlist->users = newuser;
5468
5469 cur_arg = 2;
5470
5471 while (*args[cur_arg]) {
5472 if (!strcmp(args[cur_arg], "password")) {
5473#ifndef CONFIG_HAP_CRYPT
5474 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5475 file, linenum);
5476 err_code |= ERR_ALERT;
5477#endif
5478 newuser->pass = strdup(args[cur_arg + 1]);
5479 cur_arg += 2;
5480 continue;
5481 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5482 newuser->pass = strdup(args[cur_arg + 1]);
5483 newuser->flags |= AU_O_INSECURE;
5484 cur_arg += 2;
5485 continue;
5486 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005487 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005488 cur_arg += 2;
5489 continue;
5490 } else {
5491 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5492 file, linenum, args[0]);
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
5496 }
5497 } else {
5498 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 }
5501
5502out:
5503 return err_code;
5504}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505
5506/*
5507 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005508 * Returns the error code, 0 if OK, or any combination of :
5509 * - ERR_ABORT: must abort ASAP
5510 * - ERR_FATAL: we can continue parsing but not start the service
5511 * - ERR_WARN: a warning has been emitted
5512 * - ERR_ALERT: an alert has been emitted
5513 * Only the two first ones can stop processing, the two others are just
5514 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005516int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005518 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 FILE *f;
5520 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005522 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 if ((f=fopen(file,"r")) == NULL)
5525 return -1;
5526
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005527 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005528 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005529 char *end;
5530 char *args[MAX_LINE_ARGS + 1];
5531 char *line = thisline;
5532
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 linenum++;
5534
5535 end = line + strlen(line);
5536
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005537 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5538 /* Check if we reached the limit and the last char is not \n.
5539 * Watch out for the last line without the terminating '\n'!
5540 */
5541 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005542 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005544 }
5545
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005547 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 line++;
5549
5550 arg = 0;
5551 args[arg] = line;
5552
5553 while (*line && arg < MAX_LINE_ARGS) {
5554 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5555 * C equivalent value. Other combinations left unchanged (eg: \1).
5556 */
5557 if (*line == '\\') {
5558 int skip = 0;
5559 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5560 *line = line[1];
5561 skip = 1;
5562 }
5563 else if (line[1] == 'r') {
5564 *line = '\r';
5565 skip = 1;
5566 }
5567 else if (line[1] == 'n') {
5568 *line = '\n';
5569 skip = 1;
5570 }
5571 else if (line[1] == 't') {
5572 *line = '\t';
5573 skip = 1;
5574 }
5575 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005576 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 unsigned char hex1, hex2;
5578 hex1 = toupper(line[2]) - '0';
5579 hex2 = toupper(line[3]) - '0';
5580 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5581 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5582 *line = (hex1<<4) + hex2;
5583 skip = 3;
5584 }
5585 else {
5586 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005588 }
5589 }
5590 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005591 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 end -= skip;
5593 }
5594 line++;
5595 }
5596 else if (*line == '#' || *line == '\n' || *line == '\r') {
5597 /* end of string, end of loop */
5598 *line = 0;
5599 break;
5600 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005601 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005603 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005604 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 line++;
5606 args[++arg] = line;
5607 }
5608 else {
5609 line++;
5610 }
5611 }
5612
5613 /* empty line */
5614 if (!**args)
5615 continue;
5616
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005617 if (*line) {
5618 /* we had to stop due to too many args.
5619 * Let's terminate the string, print the offending part then cut the
5620 * last arg.
5621 */
5622 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5623 line++;
5624 *line = '\0';
5625
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005626 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005627 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005628 err_code |= ERR_ALERT | ERR_FATAL;
5629 args[arg] = line;
5630 }
5631
Willy Tarreau540abe42007-05-02 20:50:16 +02005632 /* zero out remaining args and ensure that at least one entry
5633 * is zeroed out.
5634 */
5635 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 args[arg] = line;
5637 }
5638
Willy Tarreau3842f002009-06-14 11:39:52 +02005639 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005640 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005641 char *tmp;
5642
Willy Tarreau3842f002009-06-14 11:39:52 +02005643 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005644 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005645 for (arg=0; *args[arg+1]; arg++)
5646 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005647 *tmp = '\0'; // fix the next arg to \0
5648 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005649 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005650 else if (!strcmp(args[0], "default")) {
5651 kwm = KWM_DEF;
5652 for (arg=0; *args[arg+1]; arg++)
5653 args[arg] = args[arg+1]; // shift args after inversion
5654 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005655
William Lallemand0f99e342011-10-12 17:50:54 +02005656 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5657 strcmp(args[0], "log") != 0) {
5658 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005659 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005660 }
5661
Willy Tarreau977b8e42006-12-29 14:19:17 +01005662 if (!strcmp(args[0], "listen") ||
5663 !strcmp(args[0], "frontend") ||
5664 !strcmp(args[0], "backend") ||
5665 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005666 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005668 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005669 cursection = strdup(args[0]);
5670 }
5671 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005673 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005674 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005675 }
5676 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005677 confsect = CFG_USERLIST;
5678 free(cursection);
5679 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005680 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005681 else if (!strcmp(args[0], "peers")) {
5682 confsect = CFG_PEERS;
5683 free(cursection);
5684 cursection = strdup(args[0]);
5685 }
5686
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 /* else it's a section keyword */
5688
5689 switch (confsect) {
5690 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005691 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 break;
5693 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005694 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005696 case CFG_USERLIST:
5697 err_code |= cfg_parse_users(file, linenum, args, kwm);
5698 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005699 case CFG_PEERS:
5700 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5701 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005703 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005704 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005706
5707 if (err_code & ERR_ABORT)
5708 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005710 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005711 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005713 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005714}
5715
Willy Tarreaubb925012009-07-23 13:36:36 +02005716/*
5717 * Returns the error code, 0 if OK, or any combination of :
5718 * - ERR_ABORT: must abort ASAP
5719 * - ERR_FATAL: we can continue parsing but not start the service
5720 * - ERR_WARN: a warning has been emitted
5721 * - ERR_ALERT: an alert has been emitted
5722 * Only the two first ones can stop processing, the two others are just
5723 * indicators.
5724 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005725int check_config_validity()
5726{
5727 int cfgerr = 0;
5728 struct proxy *curproxy = NULL;
5729 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005730 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005731 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005732 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005733 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005735 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 /*
5737 * Now, check for the integrity of all that we have collected.
5738 */
5739
5740 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005741 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005743 /* first, we will invert the proxy list order */
5744 curproxy = NULL;
5745 while (proxy) {
5746 struct proxy *next;
5747
5748 next = proxy->next;
5749 proxy->next = curproxy;
5750 curproxy = proxy;
5751 if (!next)
5752 break;
5753 proxy = next;
5754 }
5755
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005757 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005758 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005759 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005760 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005761 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005762 unsigned int next_id;
5763
Willy Tarreau050536d2012-10-04 08:47:34 +02005764 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005765 /* proxy ID not set, use automatic numbering with first
5766 * spare entry starting with next_pxid.
5767 */
5768 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5769 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5770 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005771 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005772 next_pxid++;
5773
Willy Tarreau55ea7572007-06-17 19:56:27 +02005774
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005776 /* ensure we don't keep listeners uselessly bound */
5777 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 curproxy = curproxy->next;
5779 continue;
5780 }
5781
Willy Tarreauff01a212009-03-15 13:46:16 +01005782 switch (curproxy->mode) {
5783 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005785 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005786 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5787 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005788 cfgerr++;
5789 }
5790
5791 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005792 Warning("config : servers will be ignored for %s '%s'.\n",
5793 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005794 break;
5795
5796 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005797 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005798 break;
5799
5800 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005801 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005802 break;
5803 }
5804
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005805 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005806 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005807 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005808 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5809 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005810 cfgerr++;
5811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005813 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005814 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5815 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005816 cfgerr++;
5817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005819 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005820 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5821 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005822 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005823 }
5824 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005825 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005826 /* If no LB algo is set in a backend, and we're not in
5827 * transparent mode, dispatch mode nor proxy mode, we
5828 * want to use balance roundrobin by default.
5829 */
5830 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5831 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005834
Willy Tarreau1620ec32011-08-06 17:05:02 +02005835 if (curproxy->options & PR_O_DISPATCH)
5836 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5837 else if (curproxy->options & PR_O_HTTP_PROXY)
5838 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5839 else if (curproxy->options & PR_O_TRANSP)
5840 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005841
Willy Tarreau1620ec32011-08-06 17:05:02 +02005842 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5843 if (curproxy->options & PR_O_DISABLE404) {
5844 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5845 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5846 err_code |= ERR_WARN;
5847 curproxy->options &= ~PR_O_DISABLE404;
5848 }
5849 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5850 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5851 "send-state", proxy_type_str(curproxy), curproxy->id);
5852 err_code |= ERR_WARN;
5853 curproxy->options &= ~PR_O2_CHK_SNDST;
5854 }
Willy Tarreauef781042010-01-27 11:53:01 +01005855 }
5856
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005857 /* if a default backend was specified, let's find it */
5858 if (curproxy->defbe.name) {
5859 struct proxy *target;
5860
Alex Williams96532db2009-11-01 21:27:13 -05005861 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005862 if (!target) {
5863 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5864 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005865 cfgerr++;
5866 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005867 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5868 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005869 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005870 } else {
5871 free(curproxy->defbe.name);
5872 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005873 /* we force the backend to be present on at least all of
5874 * the frontend's processes.
5875 */
5876 target->bind_proc = curproxy->bind_proc ?
5877 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005878
5879 /* Emit a warning if this proxy also has some servers */
5880 if (curproxy->srv) {
5881 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5882 curproxy->id);
5883 err_code |= ERR_WARN;
5884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 }
5886 }
5887
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005888 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005889 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5890 /* map jump target for ACT_SETBE in req_rep chain */
5891 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005892 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005893 struct proxy *target;
5894
Willy Tarreaua496b602006-12-17 23:15:24 +01005895 if (exp->action != ACT_SETBE)
5896 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005897
Alex Williams96532db2009-11-01 21:27:13 -05005898 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005899 if (!target) {
5900 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5901 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005902 cfgerr++;
5903 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005904 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5905 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005906 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005907 } else {
5908 free((void *)exp->replace);
5909 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005910 /* we force the backend to be present on at least all of
5911 * the frontend's processes.
5912 */
5913 target->bind_proc = curproxy->bind_proc ?
5914 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005915 }
5916 }
5917 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005918
5919 /* find the target proxy for 'use_backend' rules */
5920 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005921 struct proxy *target;
5922
Alex Williams96532db2009-11-01 21:27:13 -05005923 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005924
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005925 if (!target) {
5926 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5927 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005928 cfgerr++;
5929 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005930 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5931 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005932 cfgerr++;
5933 } else {
5934 free((void *)rule->be.name);
5935 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005936 /* we force the backend to be present on at least all of
5937 * the frontend's processes.
5938 */
5939 target->bind_proc = curproxy->bind_proc ?
5940 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005941 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005942 }
5943
5944 /* find the target proxy for 'use_backend' rules */
5945 list_for_each_entry(srule, &curproxy->server_rules, list) {
5946 struct server *target = findserver(curproxy, srule->srv.name);
5947
5948 if (!target) {
5949 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5950 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5951 cfgerr++;
5952 continue;
5953 }
5954 free((void *)srule->srv.name);
5955 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005956 }
5957
Emeric Brunb982a3d2010-01-04 15:45:53 +01005958 /* find the target table for 'stick' rules */
5959 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5960 struct proxy *target;
5961
Emeric Brun1d33b292010-01-04 15:47:17 +01005962 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5963 if (mrule->flags & STK_IS_STORE)
5964 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5965
Emeric Brunb982a3d2010-01-04 15:45:53 +01005966 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005967 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005968 else
5969 target = curproxy;
5970
5971 if (!target) {
5972 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5973 curproxy->id, mrule->table.name);
5974 cfgerr++;
5975 }
5976 else if (target->table.size == 0) {
5977 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5978 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5979 cfgerr++;
5980 }
Willy Tarreau12785782012-04-27 21:37:17 +02005981 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5982 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005983 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5984 cfgerr++;
5985 }
5986 else {
5987 free((void *)mrule->table.name);
5988 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005989 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005990 }
5991 }
5992
5993 /* find the target table for 'store response' rules */
5994 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5995 struct proxy *target;
5996
Emeric Brun1d33b292010-01-04 15:47:17 +01005997 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5998
Emeric Brunb982a3d2010-01-04 15:45:53 +01005999 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006000 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006001 else
6002 target = curproxy;
6003
6004 if (!target) {
6005 Alert("Proxy '%s': unable to find store table '%s'.\n",
6006 curproxy->id, mrule->table.name);
6007 cfgerr++;
6008 }
6009 else if (target->table.size == 0) {
6010 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6011 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6012 cfgerr++;
6013 }
Willy Tarreau12785782012-04-27 21:37:17 +02006014 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6015 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006016 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6017 cfgerr++;
6018 }
6019 else {
6020 free((void *)mrule->table.name);
6021 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006022 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006023 }
6024 }
6025
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006026 /* find the target table for 'tcp-request' layer 4 rules */
6027 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6028 struct proxy *target;
6029
Willy Tarreau56123282010-08-06 19:06:56 +02006030 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006031 continue;
6032
6033 if (trule->act_prm.trk_ctr.table.n)
6034 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6035 else
6036 target = curproxy;
6037
6038 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006039 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6040 curproxy->id, trule->act_prm.trk_ctr.table.n,
6041 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006042 cfgerr++;
6043 }
6044 else if (target->table.size == 0) {
6045 Alert("Proxy '%s': table '%s' used but not configured.\n",
6046 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6047 cfgerr++;
6048 }
6049 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006050 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006051 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6052 cfgerr++;
6053 }
6054 else {
6055 free(trule->act_prm.trk_ctr.table.n);
6056 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006057 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006058 * to pass a list of counters to track and allocate them right here using
6059 * stktable_alloc_data_type().
6060 */
6061 }
6062 }
6063
Willy Tarreaud1f96522010-08-03 19:34:32 +02006064 /* find the target table for 'tcp-request' layer 6 rules */
6065 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6066 struct proxy *target;
6067
Willy Tarreau56123282010-08-06 19:06:56 +02006068 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006069 continue;
6070
6071 if (trule->act_prm.trk_ctr.table.n)
6072 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6073 else
6074 target = curproxy;
6075
6076 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006077 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6078 curproxy->id, trule->act_prm.trk_ctr.table.n,
6079 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006080 cfgerr++;
6081 }
6082 else if (target->table.size == 0) {
6083 Alert("Proxy '%s': table '%s' used but not configured.\n",
6084 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6085 cfgerr++;
6086 }
6087 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006088 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006089 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6090 cfgerr++;
6091 }
6092 else {
6093 free(trule->act_prm.trk_ctr.table.n);
6094 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006095 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006096 * to pass a list of counters to track and allocate them right here using
6097 * stktable_alloc_data_type().
6098 */
6099 }
6100 }
6101
Emeric Brun32da3c42010-09-23 18:39:19 +02006102 if (curproxy->table.peers.name) {
6103 struct peers *curpeers = peers;
6104
6105 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6106 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6107 free((void *)curproxy->table.peers.name);
6108 curproxy->table.peers.p = peers;
6109 break;
6110 }
6111 }
6112
6113 if (!curpeers) {
6114 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6115 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006116 free((void *)curproxy->table.peers.name);
6117 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006118 cfgerr++;
6119 }
6120 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006121 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6122 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006123 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006124 cfgerr++;
6125 }
6126 }
6127
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006128 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006129 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006130 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6131 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6132 "proxy", curproxy->id);
6133 cfgerr++;
6134 goto out_uri_auth_compat;
6135 }
6136
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006137 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006138 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006139 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006140 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006141
Willy Tarreau95fa4692010-02-01 13:05:50 +01006142 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6143 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006144
6145 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006146 uri_auth_compat_req[i++] = "realm";
6147 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6148 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006149
Willy Tarreau95fa4692010-02-01 13:05:50 +01006150 uri_auth_compat_req[i++] = "unless";
6151 uri_auth_compat_req[i++] = "{";
6152 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6153 uri_auth_compat_req[i++] = "}";
6154 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006155
Willy Tarreauff011f22011-01-06 17:51:27 +01006156 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6157 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006158 cfgerr++;
6159 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006160 }
6161
Willy Tarreauff011f22011-01-06 17:51:27 +01006162 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006163
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006164 if (curproxy->uri_auth->auth_realm) {
6165 free(curproxy->uri_auth->auth_realm);
6166 curproxy->uri_auth->auth_realm = NULL;
6167 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006168
6169 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006170 }
6171out_uri_auth_compat:
6172
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006173 cfgerr += acl_find_targets(curproxy);
6174
Willy Tarreau2738a142006-07-08 17:28:09 +02006175 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006176 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006177 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006178 (!curproxy->timeout.connect ||
6179 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006180 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006181 " | While not properly invalid, you will certainly encounter various problems\n"
6182 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006183 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006184 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006185 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006186 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006187
Willy Tarreau1fa31262007-12-03 00:36:16 +01006188 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6189 * We must still support older configurations, so let's find out whether those
6190 * parameters have been set or must be copied from contimeouts.
6191 */
6192 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006193 if (!curproxy->timeout.tarpit ||
6194 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006195 /* tarpit timeout not set. We search in the following order:
6196 * default.tarpit, curr.connect, default.connect.
6197 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006198 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006199 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006200 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006201 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006202 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006203 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006204 }
6205 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006206 (!curproxy->timeout.queue ||
6207 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006208 /* queue timeout not set. We search in the following order:
6209 * default.queue, curr.connect, default.connect.
6210 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006211 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006212 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006213 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006214 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006215 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006216 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006217 }
6218 }
6219
Willy Tarreau1620ec32011-08-06 17:05:02 +02006220 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006221 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6222 curproxy->check_req = (char *)malloc(curproxy->check_len);
6223 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006224 }
6225
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006226 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006227 if (curproxy->nb_req_cap) {
6228 if (curproxy->mode == PR_MODE_HTTP) {
6229 curproxy->req_cap_pool = create_pool("ptrcap",
6230 curproxy->nb_req_cap * sizeof(char *),
6231 MEM_F_SHARED);
6232 } else {
6233 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6234 proxy_type_str(curproxy), curproxy->id);
6235 err_code |= ERR_WARN;
6236 curproxy->to_log &= ~LW_REQHDR;
6237 curproxy->nb_req_cap = 0;
6238 }
6239 }
6240
6241 if (curproxy->nb_rsp_cap) {
6242 if (curproxy->mode == PR_MODE_HTTP) {
6243 curproxy->rsp_cap_pool = create_pool("ptrcap",
6244 curproxy->nb_rsp_cap * sizeof(char *),
6245 MEM_F_SHARED);
6246 } else {
6247 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6248 proxy_type_str(curproxy), curproxy->id);
6249 err_code |= ERR_WARN;
6250 curproxy->to_log &= ~LW_REQHDR;
6251 curproxy->nb_rsp_cap = 0;
6252 }
6253 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006254
Willy Tarreau196729e2012-05-31 19:30:26 +02006255 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006256 if (!(curproxy->cap & PR_CAP_FE)) {
6257 if (curproxy->logformat_string != default_http_log_format &&
6258 curproxy->logformat_string != default_tcp_log_format &&
6259 curproxy->logformat_string != clf_http_log_format)
6260 free(curproxy->logformat_string);
6261 curproxy->logformat_string = NULL;
6262 }
6263
Willy Tarreau196729e2012-05-31 19:30:26 +02006264 if (curproxy->logformat_string)
6265 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6266
6267 if (curproxy->uniqueid_format_string)
6268 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6269
Willy Tarreaubaaee002006-06-26 02:48:02 +02006270 /* first, we will invert the servers list order */
6271 newsrv = NULL;
6272 while (curproxy->srv) {
6273 struct server *next;
6274
6275 next = curproxy->srv->next;
6276 curproxy->srv->next = newsrv;
6277 newsrv = curproxy->srv;
6278 if (!next)
6279 break;
6280 curproxy->srv = next;
6281 }
6282
Willy Tarreaudd701652010-05-25 23:03:02 +02006283 /* assign automatic UIDs to servers which don't have one yet */
6284 next_id = 1;
6285 newsrv = curproxy->srv;
6286 while (newsrv != NULL) {
6287 if (!newsrv->puid) {
6288 /* server ID not set, use automatic numbering with first
6289 * spare entry starting with next_svid.
6290 */
6291 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6292 newsrv->conf.id.key = newsrv->puid = next_id;
6293 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6294 }
6295 next_id++;
6296 newsrv = newsrv->next;
6297 }
6298
Willy Tarreau20697042007-11-15 23:26:18 +01006299 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006300 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301
Willy Tarreau62c3be22012-01-20 13:12:32 +01006302 /*
6303 * If this server supports a maxconn parameter, it needs a dedicated
6304 * tasks to fill the emptied slots when a connection leaves.
6305 * Also, resolve deferred tracking dependency if needed.
6306 */
6307 newsrv = curproxy->srv;
6308 while (newsrv != NULL) {
6309 if (newsrv->minconn > newsrv->maxconn) {
6310 /* Only 'minconn' was specified, or it was higher than or equal
6311 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6312 * this will avoid further useless expensive computations.
6313 */
6314 newsrv->maxconn = newsrv->minconn;
6315 } else if (newsrv->maxconn && !newsrv->minconn) {
6316 /* minconn was not specified, so we set it to maxconn */
6317 newsrv->minconn = newsrv->maxconn;
6318 }
6319
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006320#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006321 if (newsrv->use_ssl || newsrv->check.use_ssl)
6322 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006323#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006324
Willy Tarreau62c3be22012-01-20 13:12:32 +01006325 if (newsrv->trackit) {
6326 struct proxy *px;
6327 struct server *srv;
6328 char *pname, *sname;
6329
6330 pname = newsrv->trackit;
6331 sname = strrchr(pname, '/');
6332
6333 if (sname)
6334 *sname++ = '\0';
6335 else {
6336 sname = pname;
6337 pname = NULL;
6338 }
6339
6340 if (pname) {
6341 px = findproxy(pname, PR_CAP_BE);
6342 if (!px) {
6343 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6344 proxy_type_str(curproxy), curproxy->id,
6345 newsrv->id, pname);
6346 cfgerr++;
6347 goto next_srv;
6348 }
6349 } else
6350 px = curproxy;
6351
6352 srv = findserver(px, sname);
6353 if (!srv) {
6354 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6355 proxy_type_str(curproxy), curproxy->id,
6356 newsrv->id, sname);
6357 cfgerr++;
6358 goto next_srv;
6359 }
6360
6361 if (!(srv->state & SRV_CHECKED)) {
6362 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6363 "tracking as it does not have checks enabled.\n",
6364 proxy_type_str(curproxy), curproxy->id,
6365 newsrv->id, px->id, srv->id);
6366 cfgerr++;
6367 goto next_srv;
6368 }
6369
6370 if (curproxy != px &&
6371 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6372 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6373 "tracking: disable-on-404 option inconsistency.\n",
6374 proxy_type_str(curproxy), curproxy->id,
6375 newsrv->id, px->id, srv->id);
6376 cfgerr++;
6377 goto next_srv;
6378 }
6379
6380 /* if the other server is forced disabled, we have to do the same here */
6381 if (srv->state & SRV_MAINTAIN) {
6382 newsrv->state |= SRV_MAINTAIN;
6383 newsrv->state &= ~SRV_RUNNING;
6384 newsrv->health = 0;
6385 }
6386
6387 newsrv->track = srv;
6388 newsrv->tracknext = srv->tracknext;
6389 srv->tracknext = newsrv;
6390
6391 free(newsrv->trackit);
6392 newsrv->trackit = NULL;
6393 }
6394 next_srv:
6395 newsrv = newsrv->next;
6396 }
6397
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006398 /* We have to initialize the server lookup mechanism depending
6399 * on what LB algorithm was choosen.
6400 */
6401
6402 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6403 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6404 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006405 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6406 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6407 init_server_map(curproxy);
6408 } else {
6409 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6410 fwrr_init_server_groups(curproxy);
6411 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006412 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006413
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006414 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006415 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6416 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6417 fwlc_init_server_tree(curproxy);
6418 } else {
6419 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6420 fas_init_server_tree(curproxy);
6421 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006422 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006423
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006424 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006425 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6426 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6427 chash_init_server_tree(curproxy);
6428 } else {
6429 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6430 init_server_map(curproxy);
6431 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006432 break;
6433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434
6435 if (curproxy->options & PR_O_LOGASAP)
6436 curproxy->to_log &= ~LW_BYTES;
6437
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006438 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006439 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006440 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6441 proxy_type_str(curproxy), curproxy->id);
6442 err_code |= ERR_WARN;
6443 }
6444
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006445 if (curproxy->mode != PR_MODE_HTTP) {
6446 int optnum;
6447
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006448 if (curproxy->uri_auth) {
6449 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6450 proxy_type_str(curproxy), curproxy->id);
6451 err_code |= ERR_WARN;
6452 curproxy->uri_auth = NULL;
6453 }
6454
Willy Tarreau87cf5142011-08-19 22:57:24 +02006455 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006456 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6457 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6458 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006459 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006460 }
6461
6462 if (curproxy->options & PR_O_ORGTO) {
6463 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6464 "originalto", proxy_type_str(curproxy), curproxy->id);
6465 err_code |= ERR_WARN;
6466 curproxy->options &= ~PR_O_ORGTO;
6467 }
6468
6469 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6470 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6471 (curproxy->cap & cfg_opts[optnum].cap) &&
6472 (curproxy->options & cfg_opts[optnum].val)) {
6473 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6474 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6475 err_code |= ERR_WARN;
6476 curproxy->options &= ~cfg_opts[optnum].val;
6477 }
6478 }
6479
6480 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6481 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6482 (curproxy->cap & cfg_opts2[optnum].cap) &&
6483 (curproxy->options2 & cfg_opts2[optnum].val)) {
6484 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6485 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6486 err_code |= ERR_WARN;
6487 curproxy->options2 &= ~cfg_opts2[optnum].val;
6488 }
6489 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006490
Willy Tarreauefa5f512010-03-30 20:13:29 +02006491#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006492 if (curproxy->bind_hdr_occ) {
6493 curproxy->bind_hdr_occ = 0;
6494 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6495 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6496 err_code |= ERR_WARN;
6497 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006498#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006499 }
6500
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006502 * ensure that we're not cross-dressing a TCP server into HTTP.
6503 */
6504 newsrv = curproxy->srv;
6505 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006506 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006507 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6508 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006509 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006510 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006511
Willy Tarreau0cec3312011-10-31 13:49:26 +01006512 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6513 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6514 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6515 err_code |= ERR_WARN;
6516 }
6517
Willy Tarreauefa5f512010-03-30 20:13:29 +02006518#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006519 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6520 newsrv->bind_hdr_occ = 0;
6521 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6522 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6523 err_code |= ERR_WARN;
6524 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006525#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006526 newsrv = newsrv->next;
6527 }
6528
Willy Tarreauc1a21672009-08-16 22:37:44 +02006529 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006530 if (!curproxy->accept)
6531 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006532
Willy Tarreauc1a21672009-08-16 22:37:44 +02006533 if (curproxy->tcp_req.inspect_delay ||
6534 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006535 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006536
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006537 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006538 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006539 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006540 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006541
6542 /* both TCP and HTTP must check switching rules */
6543 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6544 }
6545
6546 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006547 if (curproxy->tcp_req.inspect_delay ||
6548 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6549 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6550
Emeric Brun97679e72010-09-23 17:56:44 +02006551 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6552 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6553
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006554 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006555 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006556 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006557 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006558
6559 /* If the backend does requires RDP cookie persistence, we have to
6560 * enable the corresponding analyser.
6561 */
6562 if (curproxy->options2 & PR_O2_RDPC_PRST)
6563 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6564 }
6565
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006566 /* Configure SSL for each bind line.
6567 * Note: if configuration fails at some point, the ->ctx member
6568 * remains NULL so that listeners can later detach.
6569 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006570 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6571 if (!bind_conf->is_ssl)
6572 continue;
6573#ifdef USE_OPENSSL
6574 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006575 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006576 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006577 cfgerr++;
6578 continue;
6579 }
6580
Emeric Brun4b3091e2012-09-24 15:48:52 +02006581 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006582 Alert("Unable to allocate SSL session cache.\n");
6583 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006584 continue;
6585 }
6586
Emeric Brunfc0421f2012-09-07 17:30:07 +02006587 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006588 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006589#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006590 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006591
Willy Tarreaue6b98942007-10-29 01:09:36 +01006592 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006593 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006594 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006595 if (!listener->luid) {
6596 /* listener ID not set, use automatic numbering with first
6597 * spare entry starting with next_luid.
6598 */
6599 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6600 listener->conf.id.key = listener->luid = next_id;
6601 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006602 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006603 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006604
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006605 /* enable separate counters */
6606 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6607 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6608 if (!listener->name) {
6609 sprintf(trash, "sock-%d", listener->luid);
6610 listener->name = strdup(trash);
6611 }
6612 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006613
Willy Tarreaue6b98942007-10-29 01:09:36 +01006614 if (curproxy->options & PR_O_TCP_NOLING)
6615 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006616 if (!listener->maxconn)
6617 listener->maxconn = curproxy->maxconn;
6618 if (!listener->backlog)
6619 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006620 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006621 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006622 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006623 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006624
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006625 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6626 listener->options |= LI_O_TCP_RULES;
6627
Willy Tarreaude3041d2010-05-31 10:56:17 +02006628 if (curproxy->mon_mask.s_addr)
6629 listener->options |= LI_O_CHK_MONNET;
6630
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006631 /* smart accept mode is automatic in HTTP mode */
6632 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006633 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006634 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6635 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006636 }
6637
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006638 /* Release unused SSL configs */
6639 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6640 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006641 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006642#ifdef USE_OPENSSL
6643 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006644 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006645 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006646 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006647 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006648#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006649 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006650
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006651 /* Check multi-process mode compatibility for the current proxy */
6652 if (global.nbproc > 1) {
6653 int nbproc = 0;
6654 if (curproxy->bind_proc) {
6655 int proc;
6656 for (proc = 0; proc < global.nbproc; proc++) {
6657 if (curproxy->bind_proc & (1 << proc)) {
6658 nbproc++;
6659 }
6660 }
6661 } else {
6662 nbproc = global.nbproc;
6663 }
6664 if (curproxy->table.peers.name) {
6665 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6666 curproxy->id);
6667 cfgerr++;
6668 }
6669 if (nbproc > 1) {
6670 if (curproxy->uri_auth) {
6671 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6672 curproxy->id);
6673 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6674 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6675 curproxy->id);
6676 }
6677 }
6678 if (curproxy->appsession_name) {
6679 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6680 curproxy->id);
6681 }
6682 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6683 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6684 curproxy->id);
6685 }
6686 }
6687 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006688
6689 /* create the task associated with the proxy */
6690 curproxy->task = task_new();
6691 if (curproxy->task) {
6692 curproxy->task->context = curproxy;
6693 curproxy->task->process = manage_proxy;
6694 /* no need to queue, it will be done automatically if some
6695 * listener gets limited.
6696 */
6697 curproxy->task->expire = TICK_ETERNITY;
6698 } else {
6699 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6700 curproxy->id);
6701 cfgerr++;
6702 }
6703
Willy Tarreaubaaee002006-06-26 02:48:02 +02006704 curproxy = curproxy->next;
6705 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006706
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006707 /* Check multi-process mode compatibility */
6708 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006709 if (global.stats_fe && !global.stats_fe->bind_proc) {
6710 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 +01006711 }
6712 }
6713
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006714 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6715 struct auth_users *curuser;
6716 int g;
6717
6718 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6719 unsigned int group_mask = 0;
6720 char *group = NULL;
6721
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006722 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006723 continue;
6724
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006725 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006726
6727 for (g = 0; g < curuserlist->grpcnt; g++)
6728 if (!strcmp(curuserlist->groups[g], group))
6729 break;
6730
6731 if (g == curuserlist->grpcnt) {
6732 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6733 curuserlist->name, group, curuser->user);
6734 err_code |= ERR_ALERT | ERR_FATAL;
6735 goto out;
6736 }
6737
6738 group_mask |= (1 << g);
6739 }
6740
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006741 free(curuser->u.groups);
6742 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006743 }
6744
6745 for (g = 0; g < curuserlist->grpcnt; g++) {
6746 char *user = NULL;
6747
6748 if (!curuserlist->groupusers[g])
6749 continue;
6750
6751 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6752 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6753 if (!strcmp(curuser->user, user))
6754 break;
6755
6756 if (!curuser) {
6757 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6758 curuserlist->name, user, curuserlist->groups[g]);
6759 err_code |= ERR_ALERT | ERR_FATAL;
6760 goto out;
6761 }
6762
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006763 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006764 }
6765
6766 free(curuserlist->groupusers[g]);
6767 }
6768
6769 free(curuserlist->groupusers);
6770
6771#ifdef DEBUG_AUTH
6772 for (g = 0; g < curuserlist->grpcnt; g++) {
6773 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6774
6775 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006776 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006777 fprintf(stderr, " %s", curuser->user);
6778 }
6779
6780 fprintf(stderr, "\n");
6781 }
6782#endif
6783
Willy Tarreaufbb78422011-06-05 15:38:35 +02006784 }
6785
6786 /* automatically compute fullconn if not set. We must not do it in the
6787 * loop above because cross-references are not yet fully resolved.
6788 */
6789 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6790 /* If <fullconn> is not set, let's set it to 10% of the sum of
6791 * the possible incoming frontend's maxconns.
6792 */
6793 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6794 struct proxy *fe;
6795 int total = 0;
6796
6797 /* sum up the number of maxconns of frontends which
6798 * reference this backend at least once or which are
6799 * the same one ('listen').
6800 */
6801 for (fe = proxy; fe; fe = fe->next) {
6802 struct switching_rule *rule;
6803 struct hdr_exp *exp;
6804 int found = 0;
6805
6806 if (!(fe->cap & PR_CAP_FE))
6807 continue;
6808
6809 if (fe == curproxy) /* we're on a "listen" instance */
6810 found = 1;
6811
6812 if (fe->defbe.be == curproxy) /* "default_backend" */
6813 found = 1;
6814
6815 /* check if a "use_backend" rule matches */
6816 if (!found) {
6817 list_for_each_entry(rule, &fe->switching_rules, list) {
6818 if (rule->be.backend == curproxy) {
6819 found = 1;
6820 break;
6821 }
6822 }
6823 }
6824
6825 /* check if a "reqsetbe" rule matches */
6826 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6827 if (exp->action == ACT_SETBE &&
6828 (struct proxy *)exp->replace == curproxy) {
6829 found = 1;
6830 break;
6831 }
6832 }
6833
6834 /* now we've checked all possible ways to reference a backend
6835 * from a frontend.
6836 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006837 if (!found)
6838 continue;
6839 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006840 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006841 /* we have the sum of the maxconns in <total>. We only
6842 * keep 10% of that sum to set the default fullconn, with
6843 * a hard minimum of 1 (to avoid a divide by zero).
6844 */
6845 curproxy->fullconn = (total + 9) / 10;
6846 if (!curproxy->fullconn)
6847 curproxy->fullconn = 1;
6848 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006849 }
6850
Willy Tarreau056f5682010-06-06 15:51:11 +02006851 /* initialize stick-tables on backend capable proxies. This must not
6852 * be done earlier because the data size may be discovered while parsing
6853 * other proxies.
6854 */
6855 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006856 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006857
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006858 /*
6859 * Recount currently required checks.
6860 */
6861
6862 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6863 int optnum;
6864
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006865 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6866 if (curproxy->options & cfg_opts[optnum].val)
6867 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006868
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006869 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6870 if (curproxy->options2 & cfg_opts2[optnum].val)
6871 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006872 }
6873
Willy Tarreau122541c2011-09-07 21:24:49 +02006874 if (peers) {
6875 struct peers *curpeers = peers, **last;
6876 struct peer *p, *pb;
6877
6878 /* Remove all peers sections which don't have a valid listener.
6879 * This can happen when a peers section is never referenced and
6880 * does not contain a local peer.
6881 */
6882 last = &peers;
6883 while (*last) {
6884 curpeers = *last;
6885 if (curpeers->peers_fe) {
6886 last = &curpeers->next;
6887 continue;
6888 }
6889
6890 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6891 curpeers->id, localpeer);
6892
6893 p = curpeers->remote;
6894 while (p) {
6895 pb = p->next;
6896 free(p->id);
6897 free(p);
6898 p = pb;
6899 }
6900
6901 /* Destroy and unlink this curpeers section.
6902 * Note: curpeers is backed up into *last.
6903 */
6904 free(curpeers->id);
6905 curpeers = curpeers->next;
6906 free(*last);
6907 *last = curpeers;
6908 }
6909 }
6910
Willy Tarreauac1932d2011-10-24 19:14:41 +02006911 if (!global.tune.max_http_hdr)
6912 global.tune.max_http_hdr = MAX_HTTP_HDR;
6913
Willy Tarreau34eb6712011-10-24 18:15:04 +02006914 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006915 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006916 MEM_F_SHARED);
6917
Willy Tarreaubb925012009-07-23 13:36:36 +02006918 if (cfgerr > 0)
6919 err_code |= ERR_ALERT | ERR_FATAL;
6920 out:
6921 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006922}
6923
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006924/*
6925 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6926 * parsing sessions.
6927 */
6928void cfg_register_keywords(struct cfg_kw_list *kwl)
6929{
6930 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6931}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006932
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006933/*
6934 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6935 */
6936void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6937{
6938 LIST_DEL(&kwl->list);
6939 LIST_INIT(&kwl->list);
6940}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941
6942/*
6943 * Local variables:
6944 * c-indent-level: 8
6945 * c-basic-offset: 8
6946 * End:
6947 */