blob: d8b7e6dbe382f2d2bae393220fab391b4a1586af [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 Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
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 Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020065#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020066#ifdef USE_OPENSSL
67#include <proto/ssl_sock.h>
68#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010070#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071
72
Willy Tarreauf3c69202006-07-09 16:42:34 +020073/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
74 * ssl-hello-chk option to ensure that the remote server speaks SSL.
75 *
76 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
77 */
78const char sslv3_client_hello_pkt[] = {
79 "\x16" /* ContentType : 0x16 = Hanshake */
80 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
81 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
82 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
83 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
84 "\x03\x00" /* Hello Version : 0x0300 = v3 */
85 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
86 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
87 "\x00" /* Session ID length : empty (no session ID) */
88 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
89 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
90 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
91 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
92 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
93 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
94 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
95 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
96 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
97 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
98 "\x00\x38" "\x00\x39" "\x00\x3A"
99 "\x01" /* Compression Length : 0x01 = 1 byte for types */
100 "\x00" /* Compression Type : 0x00 = NULL compression */
101};
102
Willy Tarreau3842f002009-06-14 11:39:52 +0200103/* various keyword modifiers */
104enum kw_mod {
105 KWM_STD = 0, /* normal */
106 KWM_NO, /* "no" prefixed before the keyword */
107 KWM_DEF, /* "default" prefixed before the keyword */
108};
109
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100112 const char *name;
113 unsigned int val;
114 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100115 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100117};
118
119/* proxy->options */
120static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100121{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100122 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
123 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
124 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
126 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
127 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
128 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
132 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
134 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
135 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
136 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
137 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100138#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100140#else
141 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100142#endif
143
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100145};
146
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100147/* proxy->options2 */
148static const struct cfg_opt cfg_opts2[] =
149{
150#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
152 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100154#else
155 { "splice-request", 0, 0, 0, 0 },
156 { "splice-response", 0, 0, 0, 0 },
157 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100158#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
160 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
161 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
162 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
163 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
164 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
165 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
167 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400168 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200170 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200171 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172 { NULL, 0, 0, 0 }
173};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174
Willy Tarreau6daf3432008-01-22 16:44:08 +0100175static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
177int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100178int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200180/* List head of all known configuration keywords */
181static struct cfg_kw_list cfg_keywords = {
182 .list = LIST_HEAD_INIT(cfg_keywords.list)
183};
184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185/*
186 * converts <str> to a list of listeners which are dynamically allocated.
187 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
188 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
189 * - <port> is a numerical port from 1 to 65535 ;
190 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
191 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200192 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200193 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100194static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195{
196 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100197 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 int port, end;
199
200 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200201
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 while (next && *next) {
203 struct sockaddr_storage ss;
204
205 str = next;
206 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100207 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 *next++ = 0;
209 }
210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (*str == '/') {
212 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
213 /* so compute max path */
214 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
215 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 +0200216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100218 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
219 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200220 goto fail;
221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200224 ss.ss_family = AF_UNIX;
225 if (global.unix_bind.prefix) {
226 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
227 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 }
Emeric Bruned760922010-10-22 17:59:25 +0200229 else {
230 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
231 }
232 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
234 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100235 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 ss2 = str2sa_range(str, &port, &end);
238 if (!ss2) {
239 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 if (!port) {
245 Alert("parsing [%s:%d] : missing port number: '%s'\n",
246 file, line, str);
247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 /* OK the address looks correct */
251 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
258
259 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
261 file, line, 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));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200268 l->next = curproxy->listen;
269 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
271 l->fd = -1;
272 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200273 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
285 l->perm.ux.gid = l->perm.ux.uid = -1;
286 l->perm.ux.mode = 0;
287 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 }
470 else if (!strcmp(args[0], "daemon")) {
471 global.mode |= MODE_DAEMON;
472 }
473 else if (!strcmp(args[0], "debug")) {
474 global.mode |= MODE_DEBUG;
475 }
476 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100480 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200481 }
482 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100483 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100486 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100488 else if (!strcmp(args[0], "nosplice")) {
489 global.tune.options &= ~GTUNE_USE_SPLICE;
490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491 else if (!strcmp(args[0], "quiet")) {
492 global.mode |= MODE_QUIET;
493 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 else if (!strcmp(args[0], "tune.maxpollevents")) {
495 if (global.tune.maxpollevents != 0) {
496 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT;
498 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200499 }
500 if (*(args[1]) == 0) {
501 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200504 }
505 global.tune.maxpollevents = atol(args[1]);
506 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 else if (!strcmp(args[0], "tune.maxaccept")) {
508 if (global.tune.maxaccept != 0) {
509 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200510 err_code |= ERR_ALERT;
511 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100512 }
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100517 }
518 global.tune.maxaccept = atol(args[1]);
519 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200520 else if (!strcmp(args[0], "tune.chksize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.chksize = atol(args[1]);
527 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200528 else if (!strcmp(args[0], "tune.bufsize")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.bufsize = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200537 trashlen = global.tune.bufsize;
538 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 }
540 else if (!strcmp(args[0], "tune.maxrewrite")) {
541 if (*(args[1]) == 0) {
542 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT | ERR_FATAL;
544 goto out;
545 }
546 global.tune.maxrewrite = atol(args[1]);
547 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
548 global.tune.maxrewrite = global.tune.bufsize / 2;
549 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100550 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
551 if (global.tune.client_rcvbuf != 0) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.tune.client_rcvbuf = atol(args[1]);
562 }
563 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
564 if (global.tune.server_rcvbuf != 0) {
565 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT;
567 goto out;
568 }
569 if (*(args[1]) == 0) {
570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
573 }
574 global.tune.server_rcvbuf = atol(args[1]);
575 }
576 else if (!strcmp(args[0], "tune.sndbuf.client")) {
577 if (global.tune.client_sndbuf != 0) {
578 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT;
580 goto out;
581 }
582 if (*(args[1]) == 0) {
583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587 global.tune.client_sndbuf = atol(args[1]);
588 }
589 else if (!strcmp(args[0], "tune.sndbuf.server")) {
590 if (global.tune.server_sndbuf != 0) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.server_sndbuf = atol(args[1]);
601 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200602 else if (!strcmp(args[0], "tune.pipesize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.pipesize = atol(args[1]);
609 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200610 else if (!strcmp(args[0], "tune.http.maxhdr")) {
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.max_http_hdr = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 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 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 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 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 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);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200713 else if (!strcmp(args[0], "maxconnrate")) {
714 if (global.cps_lim != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT;
717 goto out;
718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.cps_lim = atol(args[1]);
725 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 else if (!strcmp(args[0], "maxpipes")) {
727 if (global.maxpipes != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100736 }
737 global.maxpipes = atol(args[1]);
738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 else if (!strcmp(args[0], "ulimit-n")) {
740 if (global.rlimit_nofile != 0) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.rlimit_nofile = atol(args[1]);
751 }
752 else if (!strcmp(args[0], "chroot")) {
753 if (global.chroot != NULL) {
754 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.chroot = strdup(args[1]);
764 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200765 else if (!strcmp(args[0], "description")) {
766 int i, len=0;
767 char *d;
768
769 if (!*args[1]) {
770 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775
776 for(i=1; *args[i]; i++)
777 len += strlen(args[i])+1;
778
779 if (global.desc)
780 free(global.desc);
781
782 global.desc = d = (char *)calloc(1, len);
783
784 d += sprintf(d, "%s", args[1]);
785 for(i=2; *args[i]; i++)
786 d += sprintf(d, " %s", args[i]);
787 }
788 else if (!strcmp(args[0], "node")) {
789 int i;
790 char c;
791
792 for (i=0; args[1][i]; i++) {
793 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100794 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
795 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200796 break;
797 }
798
799 if (!i || args[1][i]) {
800 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
801 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
802 file, linenum, args[0]);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806
807 if (global.node)
808 free(global.node);
809
810 global.node = strdup(args[1]);
811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 else if (!strcmp(args[0], "pidfile")) {
813 if (global.pidfile != NULL) {
814 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 if (*(args[1]) == 0) {
819 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 global.pidfile = strdup(args[1]);
824 }
Emeric Bruned760922010-10-22 17:59:25 +0200825 else if (!strcmp(args[0], "unix-bind")) {
826 int cur_arg = 1;
827 while (*(args[cur_arg])) {
828 if (!strcmp(args[cur_arg], "prefix")) {
829 if (global.unix_bind.prefix != NULL) {
830 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
831 err_code |= ERR_ALERT;
832 cur_arg += 2;
833 continue;
834 }
835
836 if (*(args[cur_arg+1]) == 0) {
837 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.unix_bind.prefix = strdup(args[cur_arg+1]);
842 cur_arg += 2;
843 continue;
844 }
845
846 if (!strcmp(args[cur_arg], "mode")) {
847
848 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
849 cur_arg += 2;
850 continue;
851 }
852
853 if (!strcmp(args[cur_arg], "uid")) {
854
855 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
856 cur_arg += 2;
857 continue;
858 }
859
860 if (!strcmp(args[cur_arg], "gid")) {
861
862 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
863 cur_arg += 2;
864 continue;
865 }
866
867 if (!strcmp(args[cur_arg], "user")) {
868 struct passwd *user;
869
870 user = getpwnam(args[cur_arg + 1]);
871 if (!user) {
872 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
873 file, linenum, args[0], args[cur_arg + 1 ]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 global.unix_bind.ux.uid = user->pw_uid;
879 cur_arg += 2;
880 continue;
881 }
882
883 if (!strcmp(args[cur_arg], "group")) {
884 struct group *group;
885
886 group = getgrnam(args[cur_arg + 1]);
887 if (!group) {
888 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
889 file, linenum, args[0], args[cur_arg + 1 ]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893
894 global.unix_bind.ux.gid = group->gr_gid;
895 cur_arg += 2;
896 continue;
897 }
898
Willy Tarreaub48f9582011-09-05 01:17:06 +0200899 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200900 file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 }
William Lallemand0f99e342011-10-12 17:50:54 +0200905 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
906 /* delete previous herited or defined syslog servers */
907 struct logsrv *back;
908 struct logsrv *tmp;
909
910 if (*(args[1]) != 0) {
911 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915
916 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
917 LIST_DEL(&tmp->list);
918 free(tmp);
919 }
920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200922 struct logsrv *logsrv;
923
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 if (*(args[1]) == 0 || *(args[2]) == 0) {
925 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 }
William Lallemand0f99e342011-10-12 17:50:54 +0200929
930 logsrv = calloc(1, sizeof(struct logsrv));
931
932 logsrv->facility = get_log_facility(args[2]);
933 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->level = get_log_level(args[3]);
942 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 }
948
William Lallemand0f99e342011-10-12 17:50:54 +0200949 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200950 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200951 logsrv->minlvl = get_log_level(args[4]);
952 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200953 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 }
957 }
958
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 if (!sk) {
962 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100963 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200965 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100966 goto out;
967 }
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100969 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100970 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100971 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100972 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
973 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200974 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100975 goto out;
976 }
William Lallemand0f99e342011-10-12 17:50:54 +0200977 logsrv->addr = *sk;
978 if (!get_host_port(&logsrv->addr))
979 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
William Lallemand0f99e342011-10-12 17:50:54 +0200982 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200983 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100984 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
985 char *name;
986 int len;
987
988 if (global.log_send_hostname != NULL) {
989 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
990 err_code |= ERR_ALERT;
991 goto out;
992 }
993
994 if (*(args[1]))
995 name = args[1];
996 else
997 name = hostname;
998
999 len = strlen(name);
1000
1001 /* We'll add a space after the name to respect the log format */
1002 free(global.log_send_hostname);
1003 global.log_send_hostname = malloc(len + 2);
1004 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1005 }
Kevinm48936af2010-12-22 16:08:21 +00001006 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 free(global.log_tag);
1013 global.log_tag = strdup(args[1]);
1014 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1016 if (global.spread_checks != 0) {
1017 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT;
1019 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001025 }
1026 global.spread_checks = atol(args[1]);
1027 if (global.spread_checks < 0 || global.spread_checks > 50) {
1028 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 }
1032 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001033 struct cfg_kw_list *kwl;
1034 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001036
1037 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1038 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1039 if (kwl->kw[index].section != CFG_GLOBAL)
1040 continue;
1041 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1042 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001043 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001045 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001047 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001049 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001050 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001051 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_WARN;
1053 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001054 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001055 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001056 }
1057 }
1058 }
1059
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001063
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001065 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067}
1068
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001069void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001071 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 defproxy.mode = PR_MODE_TCP;
1073 defproxy.state = PR_STNEW;
1074 defproxy.maxconn = cfg_maxpconn;
1075 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001076
1077 defproxy.defsrv.inter = DEF_CHKINTR;
1078 defproxy.defsrv.fastinter = 0;
1079 defproxy.defsrv.downinter = 0;
1080 defproxy.defsrv.rise = DEF_RISETIME;
1081 defproxy.defsrv.fall = DEF_FALLTIME;
1082 defproxy.defsrv.check_port = 0;
1083 defproxy.defsrv.maxqueue = 0;
1084 defproxy.defsrv.minconn = 0;
1085 defproxy.defsrv.maxconn = 0;
1086 defproxy.defsrv.slowstart = 0;
1087 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1088 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1089 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090}
1091
Willy Tarreauade5ec42010-01-28 19:33:49 +01001092
1093static int create_cond_regex_rule(const char *file, int line,
1094 struct proxy *px, int dir, int action, int flags,
1095 const char *cmd, const char *reg, const char *repl,
1096 const char **cond_start)
1097{
1098 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001099 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001100 const char *err;
1101 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001102 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001103
1104 if (px == &defproxy) {
1105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto err;
1108 }
1109
1110 if (*reg == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1117 err_code |= ERR_WARN;
1118
Willy Tarreau5321c422010-01-28 20:35:13 +01001119 if (cond_start &&
1120 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001121 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1122 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1123 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127 }
1128 else if (cond_start && **cond_start) {
1129 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1130 file, line, cmd, *cond_start);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto err;
1133 }
1134
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001135 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001136 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001137 else
1138 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001139
Willy Tarreauade5ec42010-01-28 19:33:49 +01001140 preg = calloc(1, sizeof(regex_t));
1141 if (!preg) {
1142 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1143 err_code = ERR_ALERT | ERR_FATAL;
1144 goto err;
1145 }
1146
1147 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1148 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1149 err_code = ERR_ALERT | ERR_FATAL;
1150 goto err;
1151 }
1152
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001153 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001154 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001155 if (repl && err) {
1156 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1157 file, line, cmd, *err);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001163 err_code |= ERR_WARN;
1164
Willy Tarreauf4068b62012-05-08 17:37:49 +02001165 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 return err_code;
1167 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001168 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001169 free(preg);
1170 return err_code;
1171}
1172
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001174 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001175 * Returns the error code, 0 if OK, or any combination of :
1176 * - ERR_ABORT: must abort ASAP
1177 * - ERR_FATAL: we can continue parsing but not start the service
1178 * - ERR_WARN: a warning has been emitted
1179 * - ERR_ALERT: an alert has been emitted
1180 * Only the two first ones can stop processing, the two others are just
1181 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001183int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1184{
1185 static struct peers *curpeers = NULL;
1186 struct peer *newpeer = NULL;
1187 const char *err;
1188 int err_code = 0;
1189
1190 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1191
1192 err = invalid_char(args[1]);
1193 if (err) {
1194 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1195 file, linenum, *err, args[0], args[1]);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 }
1198
1199 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1200 /*
1201 * If there are two proxies with the same name only following
1202 * combinations are allowed:
1203 */
1204 if (strcmp(curpeers->id, args[1]) == 0) {
1205 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1206 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1207 err_code |= ERR_WARN;
1208 }
1209 }
1210
1211 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1213 err_code |= ERR_ALERT | ERR_ABORT;
1214 goto out;
1215 }
1216
1217 curpeers->next = peers;
1218 peers = curpeers;
1219 curpeers->conf.file = file;
1220 curpeers->conf.line = linenum;
1221 curpeers->last_change = now.tv_sec;
1222 curpeers->id = strdup(args[1]);
1223 }
1224 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1225 char *rport, *raddr;
1226 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001227 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001228
1229 if (!*args[2]) {
1230 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 err = invalid_char(args[1]);
1237 if (err) {
1238 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1239 file, linenum, *err, args[1]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243
1244 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1246 err_code |= ERR_ALERT | ERR_ABORT;
1247 goto out;
1248 }
1249
1250 /* the peers are linked backwards first */
1251 curpeers->count++;
1252 newpeer->next = curpeers->remote;
1253 curpeers->remote = newpeer;
1254 newpeer->peers = curpeers;
1255 newpeer->conf.file = file;
1256 newpeer->conf.line = linenum;
1257
1258 newpeer->last_change = now.tv_sec;
1259 newpeer->id = strdup(args[1]);
1260
1261 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001262 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001263 if (rport) {
1264 *rport++ = 0;
1265 realport = atol(rport);
1266 }
1267 if (!realport) {
1268 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272
Willy Tarreaufab5a432011-03-04 15:31:53 +01001273 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001274 free(raddr);
1275 if (!sk) {
1276 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001281 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001282 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001283 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001284
1285 if (!sk) {
1286 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1287 file, linenum, newpeer->addr.ss_family, args[2]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001292 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001293
1294 if (strcmp(newpeer->id, localpeer) == 0) {
1295 /* Current is local peer, it define a frontend */
1296 newpeer->local = 1;
1297
1298 if (!curpeers->peers_fe) {
1299 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1300 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1301 err_code |= ERR_ALERT | ERR_ABORT;
1302 goto out;
1303 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001304
Willy Tarreau237250c2011-07-29 01:49:03 +02001305 init_new_proxy(curpeers->peers_fe);
1306 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001307
1308 curpeers->peers_fe->last_change = now.tv_sec;
1309 curpeers->peers_fe->id = strdup(args[1]);
1310 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001311 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001312 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1313 curpeers->peers_fe->timeout.connect = 5000;
1314 curpeers->peers_fe->accept = peer_accept;
1315 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001316 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001317 err_code |= ERR_FATAL;
1318 goto out;
1319 }
1320 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1321 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1322 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1323 curpeers->peers_fe->listen->accept = session_accept;
1324 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1325 curpeers->peers_fe->listen->handler = process_session;
1326 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001327 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1328 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001329 }
1330 }
1331 } /* neither "peer" nor "peers" */
1332 else if (*args[0] != 0) {
1333 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
1337
1338out:
1339 return err_code;
1340}
1341
1342
Willy Tarreau3842f002009-06-14 11:39:52 +02001343int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344{
1345 static struct proxy *curproxy = NULL;
1346 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001347 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001348 int rc;
1349 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001350 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001351 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001352 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001353 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354
Willy Tarreau977b8e42006-12-29 14:19:17 +01001355 if (!strcmp(args[0], "listen"))
1356 rc = PR_CAP_LISTEN;
1357 else if (!strcmp(args[0], "frontend"))
1358 rc = PR_CAP_FE | PR_CAP_RS;
1359 else if (!strcmp(args[0], "backend"))
1360 rc = PR_CAP_BE | PR_CAP_RS;
1361 else if (!strcmp(args[0], "ruleset"))
1362 rc = PR_CAP_RS;
1363 else
1364 rc = PR_CAP_NONE;
1365
1366 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 if (!*args[1]) {
1368 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1369 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001371 err_code |= ERR_ALERT | ERR_ABORT;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001374
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001375 err = invalid_char(args[1]);
1376 if (err) {
1377 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1378 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001380 }
1381
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001382 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1383 /*
1384 * If there are two proxies with the same name only following
1385 * combinations are allowed:
1386 *
1387 * listen backend frontend ruleset
1388 * listen - - - -
1389 * backend - - OK -
1390 * frontend - OK - -
1391 * ruleset - - - -
1392 */
1393
1394 if (!strcmp(curproxy->id, args[1]) &&
1395 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1396 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001397 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1398 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1399 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001400 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001401 }
1402 }
1403
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_ABORT;
1407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001409
Willy Tarreau97cb7802010-01-03 20:23:58 +01001410 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->next = proxy;
1412 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 curproxy->conf.file = file;
1414 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001415 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
1419 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001421 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001422 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001423 err_code |= ERR_FATAL;
1424 goto out;
1425 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001426 new = curproxy->listen;
1427 while (new != last) {
1428 new->conf.file = file;
1429 new->conf.line = linenum;
1430 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001431 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434
1435 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001436 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001437 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001438
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001441 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001442 curproxy->no_options = defproxy.no_options;
1443 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001444 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001445 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001446 curproxy->except_net = defproxy.except_net;
1447 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001448 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001449 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001451 if (defproxy.fwdfor_hdr_len) {
1452 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1453 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1454 }
1455
Willy Tarreaub86db342009-11-30 11:50:16 +01001456 if (defproxy.orgto_hdr_len) {
1457 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1458 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1459 }
1460
Mark Lamourinec2247f02012-01-04 13:02:01 -05001461 if (defproxy.server_id_hdr_len) {
1462 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1463 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1464 }
1465
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466 if (curproxy->cap & PR_CAP_FE) {
1467 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001468 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001469 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470
1471 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001472 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1473 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474
1475 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478 if (curproxy->cap & PR_CAP_BE) {
1479 curproxy->fullconn = defproxy.fullconn;
1480 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001482 if (defproxy.check_req) {
1483 curproxy->check_req = calloc(1, defproxy.check_len);
1484 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1485 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001488 if (defproxy.expect_str) {
1489 curproxy->expect_str = strdup(defproxy.expect_str);
1490 if (defproxy.expect_regex) {
1491 /* note: this regex is known to be valid */
1492 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1493 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1494 }
1495 }
1496
Willy Tarreau67402132012-05-31 20:40:20 +02001497 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498 if (defproxy.cookie_name)
1499 curproxy->cookie_name = strdup(defproxy.cookie_name);
1500 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001501 if (defproxy.cookie_domain)
1502 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001503
Willy Tarreau31936852010-10-06 16:59:56 +02001504 if (defproxy.cookie_maxidle)
1505 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1506
1507 if (defproxy.cookie_maxlife)
1508 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1509
Emeric Brun647caf12009-06-30 17:57:00 +02001510 if (defproxy.rdp_cookie_name)
1511 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1512 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1513
Willy Tarreau01732802007-11-01 22:48:15 +01001514 if (defproxy.url_param_name)
1515 curproxy->url_param_name = strdup(defproxy.url_param_name);
1516 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001517
Benoitaffb4812009-03-25 13:02:10 +01001518 if (defproxy.hh_name)
1519 curproxy->hh_name = strdup(defproxy.hh_name);
1520 curproxy->hh_len = defproxy.hh_len;
1521 curproxy->hh_match_domain = defproxy.hh_match_domain;
1522
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001523 if (defproxy.iface_name)
1524 curproxy->iface_name = strdup(defproxy.iface_name);
1525 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001528 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001529 if (defproxy.capture_name)
1530 curproxy->capture_name = strdup(defproxy.capture_name);
1531 curproxy->capture_namelen = defproxy.capture_namelen;
1532 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001536 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001537 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001538 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001539 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 curproxy->uri_auth = defproxy.uri_auth;
1541 curproxy->mon_net = defproxy.mon_net;
1542 curproxy->mon_mask = defproxy.mon_mask;
1543 if (defproxy.monitor_uri)
1544 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1545 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001546 if (defproxy.defbe.name)
1547 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001548
1549 /* get either a pointer to the logformat string or a copy of it */
1550 curproxy->logformat_string = defproxy.logformat_string;
1551 if (curproxy->logformat_string &&
1552 curproxy->logformat_string != default_http_log_format &&
1553 curproxy->logformat_string != default_tcp_log_format &&
1554 curproxy->logformat_string != clf_http_log_format)
1555 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 }
1557
1558 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001559 curproxy->timeout.connect = defproxy.timeout.connect;
1560 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001561 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001562 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001563 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001564 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001565 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001566 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 curproxy->source_addr = defproxy.source_addr;
1568 }
1569
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001571
1572 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001573 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001574 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001575 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001576 LIST_INIT(&node->list);
1577 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1578 }
1579
Willy Tarreau196729e2012-05-31 19:30:26 +02001580 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1581 if (curproxy->uniqueid_format_string)
1582 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001583
1584 /* copy default header unique id */
1585 if (defproxy.header_unique_id)
1586 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1587
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001589 curproxy->conf.used_listener_id = EB_ROOT;
1590 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001591
Willy Tarreau93893792009-07-23 13:19:11 +02001592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 }
1594 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1595 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001596 /* FIXME-20070101: we should do this too at the end of the
1597 * config parsing to free all default values.
1598 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(defproxy.check_req);
1600 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001601 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001602 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001603 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001604 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001605 free(defproxy.capture_name);
1606 free(defproxy.monitor_uri);
1607 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001608 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001609 free(defproxy.fwdfor_hdr_name);
1610 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001611 free(defproxy.orgto_hdr_name);
1612 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001613 free(defproxy.server_id_hdr_name);
1614 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001615 free(defproxy.expect_str);
1616 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001617
Willy Tarreau39b06652012-06-01 10:58:06 +02001618 if (defproxy.logformat_string != default_http_log_format &&
1619 defproxy.logformat_string != default_tcp_log_format &&
1620 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001621 free(defproxy.logformat_string);
1622
1623 free(defproxy.uniqueid_format_string);
1624
Willy Tarreaua534fea2008-08-03 12:19:50 +02001625 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001626 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001627
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 /* we cannot free uri_auth because it might already be used */
1629 init_default_instance();
1630 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634 else if (curproxy == NULL) {
1635 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
1639
Willy Tarreau977b8e42006-12-29 14:19:17 +01001640
1641 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001643 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001644 int cur_arg;
1645
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 if (curproxy == &defproxy) {
1647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653
Emeric Bruned760922010-10-22 17:59:25 +02001654 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001655 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001660
1661 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001662
1663 /* NOTE: the following line might create several listeners if there
1664 * are comma-separated IPs or port ranges. So all further processing
1665 * will have to be applied to all listeners created after last_listen.
1666 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001667 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001671
Willy Tarreau90a570f2009-10-04 20:54:54 +02001672 new_listen = curproxy->listen;
1673 while (new_listen != last_listen) {
1674 new_listen->conf.file = file;
1675 new_listen->conf.line = linenum;
1676 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001677 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001678 }
1679
Emeric Bruned760922010-10-22 17:59:25 +02001680 /* Set default global rights and owner for unix bind */
1681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1683 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001684 cur_arg = 2;
1685 while (*(args[cur_arg])) {
1686 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1687#ifdef SO_BINDTODEVICE
1688 struct listener *l;
1689
Emeric Bruned760922010-10-22 17:59:25 +02001690 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1691 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1692 file, linenum, args[0], args[cur_arg]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001697 if (!*args[cur_arg + 1]) {
1698 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001702 }
1703
1704 for (l = curproxy->listen; l != last_listen; l = l->next)
1705 l->interface = strdup(args[cur_arg + 1]);
1706
1707 global.last_checks |= LSTCHK_NETADM;
1708
1709 cur_arg += 2;
1710 continue;
1711#else
1712 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1713 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001716#endif
1717 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001718 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1719#ifdef TCP_MAXSEG
1720 struct listener *l;
1721 int mss;
1722
Emeric Bruned760922010-10-22 17:59:25 +02001723 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1724 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1725 file, linenum, args[0], args[cur_arg]);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
Willy Tarreaube1b9182009-06-14 18:48:19 +02001730 if (!*args[cur_arg + 1]) {
1731 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1732 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001735 }
1736
Willy Tarreau48a7e722010-12-24 15:26:39 +01001737 mss = atoi(args[cur_arg + 1]);
1738 if (!mss || abs(mss) > 65535) {
1739 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001743 }
1744
1745 for (l = curproxy->listen; l != last_listen; l = l->next)
1746 l->maxseg = mss;
1747
1748 cur_arg += 2;
1749 continue;
1750#else
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001755#endif
1756 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001757
1758 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1759#ifdef TCP_DEFER_ACCEPT
1760 struct listener *l;
1761
1762 for (l = curproxy->listen; l != last_listen; l = l->next)
1763 l->options |= LI_O_DEF_ACCEPT;
1764
1765 cur_arg ++;
1766 continue;
1767#else
1768 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1769 file, linenum, args[0], args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772#endif
1773 }
1774
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001775 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001776#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001777 struct listener *l;
1778
Emeric Bruned760922010-10-22 17:59:25 +02001779 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1780 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1781 file, linenum, args[0], args[cur_arg]);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001786 for (l = curproxy->listen; l != last_listen; l = l->next)
1787 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001788
1789 cur_arg ++;
1790 continue;
1791#else
1792 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1793 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001796#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001797 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798
Emeric Brun6e159292012-05-18 16:32:13 +02001799 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1800#ifdef USE_OPENSSL
1801 struct listener *l;
1802
1803 if (!*args[cur_arg + 1]) {
1804 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1805 file, linenum, args[0]);
1806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
1808 }
1809
1810 for (l = curproxy->listen; l != last_listen; l = l->next)
1811 l->ssl_cert = strdup(args[cur_arg + 1]);
1812
1813 cur_arg += 2;
1814 continue;
1815#else
1816 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1817 file, linenum, args[0], args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820#endif
1821 }
1822
Willy Tarreau8a956912010-10-15 14:27:08 +02001823 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1824 struct listener *l;
1825
1826 for (l = curproxy->listen; l != last_listen; l = l->next)
1827 l->options |= LI_O_ACC_PROXY;
1828
1829 cur_arg ++;
1830 continue;
1831 }
1832
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001833 if (!strcmp(args[cur_arg], "name")) {
1834 struct listener *l;
1835
1836 for (l = curproxy->listen; l != last_listen; l = l->next)
1837 l->name = strdup(args[cur_arg + 1]);
1838
1839 cur_arg += 2;
1840 continue;
1841 }
1842
1843 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001844 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001845 struct listener *l;
1846
1847 if (curproxy->listen->next != last_listen) {
1848 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1849 file, linenum, args[cur_arg]);
1850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
1852 }
1853
1854 if (!*args[cur_arg + 1]) {
1855 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1856 file, linenum, args[cur_arg]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859 }
1860
1861 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001862 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001863
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001864 if (curproxy->listen->luid <= 0) {
1865 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001866 file, linenum);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001871 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1872 if (node) {
1873 l = container_of(node, struct listener, conf.id);
1874 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1875 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1880
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001881 cur_arg += 2;
1882 continue;
1883 }
1884
Emeric Bruned760922010-10-22 17:59:25 +02001885 if (!strcmp(args[cur_arg], "mode")) {
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893
1894 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1895
1896 cur_arg += 2;
1897 continue;
1898 }
1899
1900 if (!strcmp(args[cur_arg], "uid")) {
1901
1902 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1903 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1904 file, linenum, args[0], args[cur_arg]);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908
1909 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1910 cur_arg += 2;
1911 continue;
1912 }
1913
1914 if (!strcmp(args[cur_arg], "gid")) {
1915
1916 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1917 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1918 file, linenum, args[0], args[cur_arg]);
1919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
1921 }
1922
1923 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1924 cur_arg += 2;
1925 continue;
1926 }
1927
1928 if (!strcmp(args[cur_arg], "user")) {
1929 struct passwd *user;
1930
1931 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1932 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1933 file, linenum, args[0], args[cur_arg]);
1934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
1936 }
1937 user = getpwnam(args[cur_arg + 1]);
1938 if (!user) {
1939 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1940 file, linenum, args[0], args[cur_arg + 1 ]);
1941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
1943 }
1944
1945 curproxy->listen->perm.ux.uid = user->pw_uid;
1946 cur_arg += 2;
1947 continue;
1948 }
1949
1950 if (!strcmp(args[cur_arg], "group")) {
1951 struct group *group;
1952
1953 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1954 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1955 file, linenum, args[0], args[cur_arg]);
1956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
1958 }
1959 group = getgrnam(args[cur_arg + 1]);
1960 if (!group) {
1961 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1962 file, linenum, args[0], args[cur_arg + 1 ]);
1963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
1965 }
1966
1967 curproxy->listen->perm.ux.gid = group->gr_gid;
1968 cur_arg += 2;
1969 continue;
1970 }
1971
Willy Tarreaub48f9582011-09-05 01:17:06 +02001972 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001976 }
Willy Tarreau93893792009-07-23 13:19:11 +02001977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 }
1979 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1980 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1981 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1982 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 /* flush useless bits */
1990 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001993 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996
Willy Tarreau1c47f852006-07-09 08:22:27 +02001997 if (!*args[1]) {
1998 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002002 }
2003
Willy Tarreaua534fea2008-08-03 12:19:50 +02002004 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002005 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002006 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002007 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002008 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2009
Willy Tarreau93893792009-07-23 13:19:11 +02002010 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2013 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2014 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2015 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2016 else {
2017 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 }
2021 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002022 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002023 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002024
2025 if (curproxy == &defproxy) {
2026 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002030 }
2031
2032 if (!*args[1]) {
2033 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002037 }
2038
2039 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002040 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002042 if (curproxy->uuid <= 0) {
2043 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002047 }
2048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002049 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2050 if (node) {
2051 struct proxy *target = container_of(node, struct proxy, conf.id);
2052 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2053 file, linenum, proxy_type_str(curproxy), curproxy->id,
2054 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002059 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002060 else if (!strcmp(args[0], "description")) {
2061 int i, len=0;
2062 char *d;
2063
Cyril Bonté99ed3272010-01-24 23:29:44 +01002064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2066 file, linenum, args[0]);
2067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
2069 }
2070
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002071 if (!*args[1]) {
2072 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2073 file, linenum, args[0]);
2074 return -1;
2075 }
2076
2077 for(i=1; *args[i]; i++)
2078 len += strlen(args[i])+1;
2079
2080 d = (char *)calloc(1, len);
2081 curproxy->desc = d;
2082
2083 d += sprintf(d, "%s", args[1]);
2084 for(i=2; *args[i]; i++)
2085 d += sprintf(d, " %s", args[i]);
2086
2087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2089 curproxy->state = PR_STSTOPPED;
2090 }
2091 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2092 curproxy->state = PR_STNEW;
2093 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002094 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2095 int cur_arg = 1;
2096 unsigned int set = 0;
2097
2098 while (*args[cur_arg]) {
2099 int u;
2100 if (strcmp(args[cur_arg], "all") == 0) {
2101 set = 0;
2102 break;
2103 }
2104 else if (strcmp(args[cur_arg], "odd") == 0) {
2105 set |= 0x55555555;
2106 }
2107 else if (strcmp(args[cur_arg], "even") == 0) {
2108 set |= 0xAAAAAAAA;
2109 }
2110 else {
2111 u = str2uic(args[cur_arg]);
2112 if (u < 1 || u > 32) {
2113 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2114 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002117 }
2118 if (u > global.nbproc) {
2119 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002122 }
2123 set |= 1 << (u - 1);
2124 }
2125 cur_arg++;
2126 }
2127 curproxy->bind_proc = set;
2128 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002129 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002130 if (curproxy == &defproxy) {
2131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002134 }
2135
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2139 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002140 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002141 }
2142
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002143 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2144 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2145 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002148 }
2149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2151 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 if (*(args[1]) == 0) {
2157 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002162
Willy Tarreau67402132012-05-31 20:40:20 +02002163 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002164 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002165 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002166 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->cookie_name = strdup(args[1]);
2168 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002169
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 cur_arg = 2;
2171 while (*(args[cur_arg])) {
2172 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002173 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 }
2175 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002176 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002179 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 }
2181 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002182 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }
2184 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002185 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002187 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002188 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002191 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002193 else if (!strcmp(args[cur_arg], "httponly")) {
2194 curproxy->ck_opts |= PR_CK_HTTPONLY;
2195 }
2196 else if (!strcmp(args[cur_arg], "secure")) {
2197 curproxy->ck_opts |= PR_CK_SECURE;
2198 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002199 else if (!strcmp(args[cur_arg], "domain")) {
2200 if (!*args[cur_arg + 1]) {
2201 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2202 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002205 }
2206
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002207 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002208 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002209 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2210 " dots nor does not start with a dot."
2211 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002212 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002213 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002214 }
2215
2216 err = invalid_domainchar(args[cur_arg + 1]);
2217 if (err) {
2218 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2219 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002222 }
2223
Willy Tarreau68a897b2009-12-03 23:28:34 +01002224 if (!curproxy->cookie_domain) {
2225 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2226 } else {
2227 /* one domain was already specified, add another one by
2228 * building the string which will be returned along with
2229 * the cookie.
2230 */
2231 char *new_ptr;
2232 int new_len = strlen(curproxy->cookie_domain) +
2233 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2234 new_ptr = malloc(new_len);
2235 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2236 free(curproxy->cookie_domain);
2237 curproxy->cookie_domain = new_ptr;
2238 }
Willy Tarreau31936852010-10-06 16:59:56 +02002239 cur_arg++;
2240 }
2241 else if (!strcmp(args[cur_arg], "maxidle")) {
2242 unsigned int maxidle;
2243 const char *res;
2244
2245 if (!*args[cur_arg + 1]) {
2246 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2247 file, linenum, args[cur_arg]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
2252 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2253 if (res) {
2254 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2255 file, linenum, *res, args[cur_arg]);
2256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
2258 }
2259 curproxy->cookie_maxidle = maxidle;
2260 cur_arg++;
2261 }
2262 else if (!strcmp(args[cur_arg], "maxlife")) {
2263 unsigned int maxlife;
2264 const char *res;
2265
2266 if (!*args[cur_arg + 1]) {
2267 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2268 file, linenum, args[cur_arg]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272
2273 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2274 if (res) {
2275 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2276 file, linenum, *res, args[cur_arg]);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 cur_arg++;
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002284 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 +02002285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 cur_arg++;
2290 }
Willy Tarreau67402132012-05-31 20:40:20 +02002291 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2293 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 }
2296
Willy Tarreau67402132012-05-31 20:40:20 +02002297 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2299 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002302
Willy Tarreau67402132012-05-31 20:40:20 +02002303 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002304 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2305 file, linenum);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002309 else if (!strcmp(args[0], "persist")) { /* persist */
2310 if (*(args[1]) == 0) {
2311 Alert("parsing [%s:%d] : missing persist method.\n",
2312 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002315 }
2316
2317 if (!strncmp(args[1], "rdp-cookie", 10)) {
2318 curproxy->options2 |= PR_O2_RDPC_PRST;
2319
Emeric Brunb982a3d2010-01-04 15:45:53 +01002320 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002321 const char *beg, *end;
2322
2323 beg = args[1] + 11;
2324 end = strchr(beg, ')');
2325
2326 if (!end || end == beg) {
2327 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2328 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002331 }
2332
2333 free(curproxy->rdp_cookie_name);
2334 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2335 curproxy->rdp_cookie_len = end-beg;
2336 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002337 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002338 free(curproxy->rdp_cookie_name);
2339 curproxy->rdp_cookie_name = strdup("msts");
2340 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2341 }
2342 else { /* syntax */
2343 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2344 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002347 }
2348 }
2349 else {
2350 Alert("parsing [%s:%d] : unknown persist method.\n",
2351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002354 }
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002357 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002359 if (curproxy == &defproxy) {
2360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
Willy Tarreau977b8e42006-12-29 14:19:17 +01002365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002369 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 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 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002375 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 curproxy->appsession_name = strdup(args[1]);
2377 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2378 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002379 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2380 if (err) {
2381 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2382 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002385 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002386 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002387
Willy Tarreau51041c72007-09-09 21:56:53 +02002388 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_ABORT;
2391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002393
2394 cur_arg = 6;
2395 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002396 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2397 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002398 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002399 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002400 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002401 } else if (!strcmp(args[cur_arg], "prefix")) {
2402 curproxy->options2 |= PR_O2_AS_PFX;
2403 } else if (!strcmp(args[cur_arg], "mode")) {
2404 if (!*args[cur_arg + 1]) {
2405 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2406 file, linenum, args[0], args[cur_arg]);
2407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
2409 }
2410
2411 cur_arg++;
2412 if (!strcmp(args[cur_arg], "query-string")) {
2413 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2414 curproxy->options2 |= PR_O2_AS_M_QS;
2415 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2416 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2417 curproxy->options2 |= PR_O2_AS_M_PP;
2418 } else {
2419 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002424 cur_arg++;
2425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 } /* Url App Session */
2427 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002428 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002432 if (curproxy == &defproxy) {
2433 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (*(args[4]) == 0) {
2439 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2440 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002444 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 curproxy->capture_name = strdup(args[2]);
2446 curproxy->capture_namelen = strlen(curproxy->capture_name);
2447 curproxy->capture_len = atol(args[4]);
2448 if (curproxy->capture_len >= CAPTURE_LEN) {
2449 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2450 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 curproxy->capture_len = CAPTURE_LEN - 1;
2453 }
2454 curproxy->to_log |= LW_COOKIE;
2455 }
2456 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2457 struct cap_hdr *hdr;
2458
2459 if (curproxy == &defproxy) {
2460 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 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
2464
2465 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2466 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2467 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
2471
2472 hdr = calloc(sizeof(struct cap_hdr), 1);
2473 hdr->next = curproxy->req_cap;
2474 hdr->name = strdup(args[3]);
2475 hdr->namelen = strlen(args[3]);
2476 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002477 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 hdr->index = curproxy->nb_req_cap++;
2479 curproxy->req_cap = hdr;
2480 curproxy->to_log |= LW_REQHDR;
2481 }
2482 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2483 struct cap_hdr *hdr;
2484
2485 if (curproxy == &defproxy) {
2486 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 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490
2491 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2492 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2493 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
2497 hdr = calloc(sizeof(struct cap_hdr), 1);
2498 hdr->next = curproxy->rsp_cap;
2499 hdr->name = strdup(args[3]);
2500 hdr->namelen = strlen(args[3]);
2501 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002502 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 hdr->index = curproxy->nb_rsp_cap++;
2504 curproxy->rsp_cap = hdr;
2505 curproxy->to_log |= LW_RSPHDR;
2506 }
2507 else {
2508 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 if (*(args[1]) == 0) {
2519 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524 curproxy->conn_retries = atol(args[1]);
2525 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002526 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002527 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002528
2529 if (curproxy == &defproxy) {
2530 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534
Willy Tarreauff011f22011-01-06 17:51:27 +01002535 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 +01002536 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2537 file, linenum, args[0]);
2538 err_code |= ERR_WARN;
2539 }
2540
Willy Tarreauff011f22011-01-06 17:51:27 +01002541 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002542
Willy Tarreauff011f22011-01-06 17:51:27 +01002543 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002544 err_code |= ERR_ALERT | ERR_ABORT;
2545 goto out;
2546 }
2547
Willy Tarreauff011f22011-01-06 17:51:27 +01002548 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2549 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002550 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002551 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2552 /* set the header name and length into the proxy structure */
2553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2554 err_code |= ERR_WARN;
2555
2556 if (!*args[1]) {
2557 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2558 file, linenum, args[0]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562
2563 /* set the desired header name */
2564 free(curproxy->server_id_hdr_name);
2565 curproxy->server_id_hdr_name = strdup(args[1]);
2566 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2567 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002568 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002569 if (curproxy == &defproxy) {
2570 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002573 }
2574
Willy Tarreauef6494c2010-01-28 17:12:36 +01002575 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002576 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002580 }
2581
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002582 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2583 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2584 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002587 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002588
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002589 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002590 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002591 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002592 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 struct redirect_rule *rule;
2594 int cur_arg;
2595 int type = REDIRECT_TYPE_NONE;
2596 int code = 302;
2597 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002598 char *cookie = NULL;
2599 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002600 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601
Cyril Bonté99ed3272010-01-24 23:29:44 +01002602 if (curproxy == &defproxy) {
2603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
2606 }
2607
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 cur_arg = 1;
2609 while (*(args[cur_arg])) {
2610 if (!strcmp(args[cur_arg], "location")) {
2611 if (!*args[cur_arg + 1]) {
2612 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2613 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002616 }
2617
2618 type = REDIRECT_TYPE_LOCATION;
2619 cur_arg++;
2620 destination = args[cur_arg];
2621 }
2622 else if (!strcmp(args[cur_arg], "prefix")) {
2623 if (!*args[cur_arg + 1]) {
2624 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2625 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 }
2629
2630 type = REDIRECT_TYPE_PREFIX;
2631 cur_arg++;
2632 destination = args[cur_arg];
2633 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002634 else if (!strcmp(args[cur_arg], "set-cookie")) {
2635 if (!*args[cur_arg + 1]) {
2636 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2637 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 }
2641
2642 cur_arg++;
2643 cookie = args[cur_arg];
2644 cookie_set = 1;
2645 }
2646 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2647 if (!*args[cur_arg + 1]) {
2648 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002652 }
2653
2654 cur_arg++;
2655 cookie = args[cur_arg];
2656 cookie_set = 0;
2657 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658 else if (!strcmp(args[cur_arg],"code")) {
2659 if (!*args[cur_arg + 1]) {
2660 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2661 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 }
2665 cur_arg++;
2666 code = atol(args[cur_arg]);
2667 if (code < 301 || code > 303) {
2668 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2669 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 }
2673 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002674 else if (!strcmp(args[cur_arg],"drop-query")) {
2675 flags |= REDIRECT_FLAG_DROP_QS;
2676 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002677 else if (!strcmp(args[cur_arg],"append-slash")) {
2678 flags |= REDIRECT_FLAG_APPEND_SLASH;
2679 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 else if (strcmp(args[cur_arg], "if") == 0 ||
2681 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002682 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002683 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002684 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2685 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002689 break;
2690 }
2691 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002692 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002696 }
2697 cur_arg++;
2698 }
2699
2700 if (type == REDIRECT_TYPE_NONE) {
2701 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002705 }
2706
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002707 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2708 rule->cond = cond;
2709 rule->rdr_str = strdup(destination);
2710 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002711 if (cookie) {
2712 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002713 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002714 */
2715 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002716 if (cookie_set) {
2717 rule->cookie_str = malloc(rule->cookie_len + 10);
2718 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2719 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2720 rule->cookie_len += 9;
2721 } else {
2722 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002723 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002724 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2725 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002726 }
2727 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002728 rule->type = type;
2729 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002730 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002731 LIST_INIT(&rule->list);
2732 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002733 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2734 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002735 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002736 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002737 struct switching_rule *rule;
2738
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 }
2744
Willy Tarreau55ea7572007-06-17 19:56:27 +02002745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002747
2748 if (*(args[1]) == 0) {
2749 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002752 }
2753
Willy Tarreauef6494c2010-01-28 17:12:36 +01002754 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002755 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2756 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002759 }
2760
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002761 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2762 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2763 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002766 }
2767
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002768 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002769
Willy Tarreau55ea7572007-06-17 19:56:27 +02002770 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2771 rule->cond = cond;
2772 rule->be.name = strdup(args[1]);
2773 LIST_INIT(&rule->list);
2774 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2775 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002776 else if (strcmp(args[0], "use-server") == 0) {
2777 struct server_rule *rule;
2778
2779 if (curproxy == &defproxy) {
2780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
2785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2786 err_code |= ERR_WARN;
2787
2788 if (*(args[1]) == 0) {
2789 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
2794 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2795 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2796 file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2802 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2803 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
2808 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2809
2810 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2811 rule->cond = cond;
2812 rule->srv.name = strdup(args[1]);
2813 LIST_INIT(&rule->list);
2814 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2815 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2816 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002817 else if ((!strcmp(args[0], "force-persist")) ||
2818 (!strcmp(args[0], "ignore-persist"))) {
2819 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002820
2821 if (curproxy == &defproxy) {
2822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825 }
2826
2827 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2828 err_code |= ERR_WARN;
2829
Willy Tarreauef6494c2010-01-28 17:12:36 +01002830 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002831 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2832 file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002837 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2838 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2839 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002844 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002845
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002846 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002847 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002848 if (!strcmp(args[0], "force-persist")) {
2849 rule->type = PERSIST_TYPE_FORCE;
2850 } else {
2851 rule->type = PERSIST_TYPE_IGNORE;
2852 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002853 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002854 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002855 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002856 else if (!strcmp(args[0], "stick-table")) {
2857 int myidx = 1;
2858
Emeric Brun32da3c42010-09-23 18:39:19 +02002859 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002860 curproxy->table.type = (unsigned int)-1;
2861 while (*args[myidx]) {
2862 const char *err;
2863
2864 if (strcmp(args[myidx], "size") == 0) {
2865 myidx++;
2866 if (!*(args[myidx])) {
2867 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2868 file, linenum, args[myidx-1]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2873 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2874 file, linenum, *err, args[myidx-1]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002880 else if (strcmp(args[myidx], "peers") == 0) {
2881 myidx++;
2882 if (!*(args[myidx])) {
2883 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2884 file, linenum, args[myidx-1]);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888 curproxy->table.peers.name = strdup(args[myidx++]);
2889 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 else if (strcmp(args[myidx], "expire") == 0) {
2891 myidx++;
2892 if (!*(args[myidx])) {
2893 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2894 file, linenum, args[myidx-1]);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
2897 }
2898 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2899 if (err) {
2900 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2901 file, linenum, *err, args[myidx-1]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002906 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002907 }
2908 else if (strcmp(args[myidx], "nopurge") == 0) {
2909 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002910 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 }
2912 else if (strcmp(args[myidx], "type") == 0) {
2913 myidx++;
2914 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2915 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2916 file, linenum, args[myidx]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002920 /* myidx already points to next arg */
2921 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002922 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002923 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002924 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002925
2926 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002927 nw = args[myidx];
2928 while (*nw) {
2929 /* the "store" keyword supports a comma-separated list */
2930 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002931 sa = NULL; /* store arg */
2932 while (*nw && *nw != ',') {
2933 if (*nw == '(') {
2934 *nw = 0;
2935 sa = ++nw;
2936 while (*nw != ')') {
2937 if (!*nw) {
2938 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2939 file, linenum, args[0], cw);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 nw++;
2944 }
2945 *nw = '\0';
2946 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002947 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002948 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002949 if (*nw)
2950 *nw++ = '\0';
2951 type = stktable_get_data_type(cw);
2952 if (type < 0) {
2953 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2954 file, linenum, args[0], cw);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
Willy Tarreauac782882010-06-20 10:41:54 +02002958
2959 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2960 switch (err) {
2961 case PE_NONE: break;
2962 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002963 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2964 file, linenum, args[0], cw);
2965 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002966 break;
2967
2968 case PE_ARG_MISSING:
2969 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2970 file, linenum, args[0], cw);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973
2974 case PE_ARG_NOT_USED:
2975 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2976 file, linenum, args[0], cw);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979
2980 default:
2981 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2982 file, linenum, args[0], cw);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002985 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002986 }
2987 myidx++;
2988 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002989 else {
2990 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2991 file, linenum, args[myidx]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002994 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002995 }
2996
2997 if (!curproxy->table.size) {
2998 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2999 file, linenum);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
3003
3004 if (curproxy->table.type == (unsigned int)-1) {
3005 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3006 file, linenum);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010 }
3011 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003012 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003013 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 int myidx = 0;
3015 const char *name = NULL;
3016 int flags;
3017
3018 if (curproxy == &defproxy) {
3019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
3024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3025 err_code |= ERR_WARN;
3026 goto out;
3027 }
3028
3029 myidx++;
3030 if ((strcmp(args[myidx], "store") == 0) ||
3031 (strcmp(args[myidx], "store-request") == 0)) {
3032 myidx++;
3033 flags = STK_IS_STORE;
3034 }
3035 else if (strcmp(args[myidx], "store-response") == 0) {
3036 myidx++;
3037 flags = STK_IS_STORE | STK_ON_RSP;
3038 }
3039 else if (strcmp(args[myidx], "match") == 0) {
3040 myidx++;
3041 flags = STK_IS_MATCH;
3042 }
3043 else if (strcmp(args[myidx], "on") == 0) {
3044 myidx++;
3045 flags = STK_IS_MATCH | STK_IS_STORE;
3046 }
3047 else {
3048 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052
3053 if (*(args[myidx]) == 0) {
3054 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058
David du Colombier7af46052012-05-16 14:16:48 +02003059 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003061 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065
3066 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003067 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3069 file, linenum, args[0], expr->fetch->kw);
3070 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003071 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 goto out;
3073 }
3074 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003075 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003076 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3077 file, linenum, args[0], expr->fetch->kw);
3078 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003079 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 goto out;
3081 }
3082 }
3083
3084 if (strcmp(args[myidx], "table") == 0) {
3085 myidx++;
3086 name = args[myidx++];
3087 }
3088
Willy Tarreauef6494c2010-01-28 17:12:36 +01003089 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003090 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3091 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3092 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003093 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003094 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003095 goto out;
3096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003097 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003098 else if (*(args[myidx])) {
3099 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3100 file, linenum, args[0], args[myidx]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003102 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003103 goto out;
3104 }
Emeric Brun97679e72010-09-23 17:56:44 +02003105 if (flags & STK_ON_RSP)
3106 err_code |= warnif_cond_requires_req(cond, file, linenum);
3107 else
3108 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003109
Emeric Brunb982a3d2010-01-04 15:45:53 +01003110 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3111 rule->cond = cond;
3112 rule->expr = expr;
3113 rule->flags = flags;
3114 rule->table.name = name ? strdup(name) : NULL;
3115 LIST_INIT(&rule->list);
3116 if (flags & STK_ON_RSP)
3117 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3118 else
3119 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003124
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3126 curproxy->uri_auth = NULL; /* we must detach from the default config */
3127
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003128 if (!*args[1]) {
3129 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003130 } else if (!strcmp(args[1], "admin")) {
3131 struct stats_admin_rule *rule;
3132
3133 if (curproxy == &defproxy) {
3134 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
3139 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3140 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
3143 }
3144
3145 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3146 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3147 file, linenum, args[0], args[1]);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003151 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3152 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3153 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
3158 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3159
3160 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3161 rule->cond = cond;
3162 LIST_INIT(&rule->list);
3163 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 } else if (!strcmp(args[1], "uri")) {
3165 if (*(args[2]) == 0) {
3166 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3170 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174 } else if (!strcmp(args[1], "realm")) {
3175 if (*(args[2]) == 0) {
3176 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3180 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_ABORT;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003184 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003185 unsigned interval;
3186
3187 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3188 if (err) {
3189 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3190 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003193 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003197 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003198 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003199 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003200
3201 if (curproxy == &defproxy) {
3202 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3208 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
3211 }
3212
Willy Tarreauff011f22011-01-06 17:51:27 +01003213 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3214 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003215 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3216 file, linenum, args[0]);
3217 err_code |= ERR_WARN;
3218 }
3219
Willy Tarreauff011f22011-01-06 17:51:27 +01003220 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003221
Willy Tarreauff011f22011-01-06 17:51:27 +01003222 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003223 err_code |= ERR_ALERT | ERR_ABORT;
3224 goto out;
3225 }
3226
Willy Tarreauff011f22011-01-06 17:51:27 +01003227 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3228 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 } else if (!strcmp(args[1], "auth")) {
3231 if (*(args[2]) == 0) {
3232 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3236 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_ABORT;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
3240 } else if (!strcmp(args[1], "scope")) {
3241 if (*(args[2]) == 0) {
3242 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3246 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_ABORT;
3248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 }
3250 } else if (!strcmp(args[1], "enable")) {
3251 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3252 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_ABORT;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003256 } else if (!strcmp(args[1], "hide-version")) {
3257 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_ABORT;
3260 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003261 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003262 } else if (!strcmp(args[1], "show-legends")) {
3263 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003268 } else if (!strcmp(args[1], "show-node")) {
3269
3270 if (*args[2]) {
3271 int i;
3272 char c;
3273
3274 for (i=0; args[2][i]; i++) {
3275 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003276 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3277 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003278 break;
3279 }
3280
3281 if (!i || args[2][i]) {
3282 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3283 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3284 file, linenum, args[0], args[1]);
3285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
3287 }
3288 }
3289
3290 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
3295 } else if (!strcmp(args[1], "show-desc")) {
3296 char *desc = NULL;
3297
3298 if (*args[2]) {
3299 int i, len=0;
3300 char *d;
3301
3302 for(i=2; *args[i]; i++)
3303 len += strlen(args[i])+1;
3304
3305 desc = d = (char *)calloc(1, len);
3306
3307 d += sprintf(d, "%s", args[2]);
3308 for(i=3; *args[i]; i++)
3309 d += sprintf(d, " %s", args[i]);
3310 }
3311
3312 if (!*args[2] && !global.desc)
3313 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3314 file, linenum, args[1]);
3315 else {
3316 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3317 free(desc);
3318 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3319 err_code |= ERR_ALERT | ERR_ABORT;
3320 goto out;
3321 }
3322 free(desc);
3323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003325stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003326 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 +01003327 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 }
3332 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003333 int optnum;
3334
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003335 if (*(args[1]) == '\0') {
3336 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341
3342 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3343 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003344 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3345 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3346 file, linenum, cfg_opts[optnum].name);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
Willy Tarreau93893792009-07-23 13:19:11 +02003350 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3351 err_code |= ERR_WARN;
3352 goto out;
3353 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003354
Willy Tarreau3842f002009-06-14 11:39:52 +02003355 curproxy->no_options &= ~cfg_opts[optnum].val;
3356 curproxy->options &= ~cfg_opts[optnum].val;
3357
3358 switch (kwm) {
3359 case KWM_STD:
3360 curproxy->options |= cfg_opts[optnum].val;
3361 break;
3362 case KWM_NO:
3363 curproxy->no_options |= cfg_opts[optnum].val;
3364 break;
3365 case KWM_DEF: /* already cleared */
3366 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003367 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003368
Willy Tarreau93893792009-07-23 13:19:11 +02003369 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003370 }
3371 }
3372
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003373 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3374 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003375 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3376 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3377 file, linenum, cfg_opts2[optnum].name);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
Willy Tarreau93893792009-07-23 13:19:11 +02003381 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3382 err_code |= ERR_WARN;
3383 goto out;
3384 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003385
Willy Tarreau3842f002009-06-14 11:39:52 +02003386 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3387 curproxy->options2 &= ~cfg_opts2[optnum].val;
3388
3389 switch (kwm) {
3390 case KWM_STD:
3391 curproxy->options2 |= cfg_opts2[optnum].val;
3392 break;
3393 case KWM_NO:
3394 curproxy->no_options2 |= cfg_opts2[optnum].val;
3395 break;
3396 case KWM_DEF: /* already cleared */
3397 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003398 }
Willy Tarreau93893792009-07-23 13:19:11 +02003399 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003400 }
3401 }
3402
Willy Tarreau3842f002009-06-14 11:39:52 +02003403 if (kwm != KWM_STD) {
3404 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003405 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003408 }
3409
Emeric Brun3a058f32009-06-30 18:26:00 +02003410 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003411 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003413 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003414 if (*(args[2]) != '\0') {
3415 if (!strcmp(args[2], "clf")) {
3416 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003417 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003418 } else {
3419 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003422 }
3423 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003424 if (curproxy->logformat_string != default_http_log_format &&
3425 curproxy->logformat_string != default_tcp_log_format &&
3426 curproxy->logformat_string != clf_http_log_format)
3427 free(curproxy->logformat_string);
3428 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003429 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003430 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003432 if (curproxy->logformat_string != default_http_log_format &&
3433 curproxy->logformat_string != default_tcp_log_format &&
3434 curproxy->logformat_string != clf_http_log_format)
3435 free(curproxy->logformat_string);
3436 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 else if (!strcmp(args[1], "tcpka")) {
3439 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003440 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003442
3443 if (curproxy->cap & PR_CAP_FE)
3444 curproxy->options |= PR_O_TCP_CLI_KA;
3445 if (curproxy->cap & PR_CAP_BE)
3446 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
3448 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_WARN;
3451
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003453 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003455 curproxy->options2 &= ~PR_O2_CHK_ANY;
3456 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 if (!*args[2]) { /* no argument */
3458 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3459 curproxy->check_len = strlen(DEF_CHECK_REQ);
3460 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003461 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 curproxy->check_req = (char *)malloc(reqlen);
3463 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003464 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003466 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 if (*args[4])
3468 reqlen += strlen(args[4]);
3469 else
3470 reqlen += strlen("HTTP/1.0");
3471
3472 curproxy->check_req = (char *)malloc(reqlen);
3473 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003474 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003476 }
3477 else if (!strcmp(args[1], "ssl-hello-chk")) {
3478 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003479 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003481
Willy Tarreaua534fea2008-08-03 12:19:50 +02003482 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003483 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003484 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003485 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
Willy Tarreau23677902007-05-08 23:50:35 +02003487 else if (!strcmp(args[1], "smtpchk")) {
3488 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003489 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003490 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003491 curproxy->options2 &= ~PR_O2_CHK_ANY;
3492 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003493
3494 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3495 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3496 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3497 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3498 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3499 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3500 curproxy->check_req = (char *)malloc(reqlen);
3501 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3502 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3503 } else {
3504 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3505 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3506 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3507 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3508 }
3509 }
3510 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003511 else if (!strcmp(args[1], "pgsql-check")) {
3512 /* use PostgreSQL request to check servers' health */
3513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3514 err_code |= ERR_WARN;
3515
3516 free(curproxy->check_req);
3517 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003518 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003519 curproxy->options2 |= PR_O2_PGSQL_CHK;
3520
3521 if (*(args[2])) {
3522 int cur_arg = 2;
3523
3524 while (*(args[cur_arg])) {
3525 if (strcmp(args[cur_arg], "user") == 0) {
3526 char * packet;
3527 uint32_t packet_len;
3528 uint32_t pv;
3529
3530 /* suboption header - needs additional argument for it */
3531 if (*(args[cur_arg+1]) == 0) {
3532 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3533 file, linenum, args[0], args[1], args[cur_arg]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537
3538 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3539 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3540 pv = htonl(0x30000); /* protocol version 3.0 */
3541
3542 packet = (char*) calloc(1, packet_len);
3543
3544 memcpy(packet + 4, &pv, 4);
3545
3546 /* copy "user" */
3547 memcpy(packet + 8, "user", 4);
3548
3549 /* copy username */
3550 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3551
3552 free(curproxy->check_req);
3553 curproxy->check_req = packet;
3554 curproxy->check_len = packet_len;
3555
3556 packet_len = htonl(packet_len);
3557 memcpy(packet, &packet_len, 4);
3558 cur_arg += 2;
3559 } else {
3560 /* unknown suboption - catchall */
3561 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3562 file, linenum, args[0], args[1]);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566 } /* end while loop */
3567 }
3568 }
3569
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003570 else if (!strcmp(args[1], "redis-check")) {
3571 /* use REDIS PING request to check servers' health */
3572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3573 err_code |= ERR_WARN;
3574
3575 free(curproxy->check_req);
3576 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003577 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003578 curproxy->options2 |= PR_O2_REDIS_CHK;
3579
3580 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3581 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3582 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3583 }
3584
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003585 else if (!strcmp(args[1], "mysql-check")) {
3586 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003587 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3588 err_code |= ERR_WARN;
3589
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003590 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003591 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003592 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003593 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003594
3595 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3596 * const char mysql40_client_auth_pkt[] = {
3597 * "\x0e\x00\x00" // packet length
3598 * "\x01" // packet number
3599 * "\x00\x00" // client capabilities
3600 * "\x00\x00\x01" // max packet
3601 * "haproxy\x00" // username (null terminated string)
3602 * "\x00" // filler (always 0x00)
3603 * "\x01\x00\x00" // packet length
3604 * "\x00" // packet number
3605 * "\x01" // COM_QUIT command
3606 * };
3607 */
3608
3609 if (*(args[2])) {
3610 int cur_arg = 2;
3611
3612 while (*(args[cur_arg])) {
3613 if (strcmp(args[cur_arg], "user") == 0) {
3614 char *mysqluser;
3615 int packetlen, reqlen, userlen;
3616
3617 /* suboption header - needs additional argument for it */
3618 if (*(args[cur_arg+1]) == 0) {
3619 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3620 file, linenum, args[0], args[1], args[cur_arg]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 mysqluser = args[cur_arg + 1];
3625 userlen = strlen(mysqluser);
3626 packetlen = userlen + 7;
3627 reqlen = packetlen + 9;
3628
3629 free(curproxy->check_req);
3630 curproxy->check_req = (char *)calloc(1, reqlen);
3631 curproxy->check_len = reqlen;
3632
3633 snprintf(curproxy->check_req, 4, "%c%c%c",
3634 ((unsigned char) packetlen & 0xff),
3635 ((unsigned char) (packetlen >> 8) & 0xff),
3636 ((unsigned char) (packetlen >> 16) & 0xff));
3637
3638 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003639 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003640 curproxy->check_req[8] = 1;
3641 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3642 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3643 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3644 cur_arg += 2;
3645 } else {
3646 /* unknown suboption - catchall */
3647 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3648 file, linenum, args[0], args[1]);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
3652 } /* end while loop */
3653 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003655 else if (!strcmp(args[1], "ldap-check")) {
3656 /* use LDAP request to check servers' health */
3657 free(curproxy->check_req);
3658 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003659 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003660 curproxy->options2 |= PR_O2_LDAP_CHK;
3661
3662 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3663 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3664 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3665 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003666 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003667 int cur_arg;
3668
3669 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3670 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003671 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003672
Willy Tarreau87cf5142011-08-19 22:57:24 +02003673 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003674
3675 free(curproxy->fwdfor_hdr_name);
3676 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3677 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3678
3679 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3680 cur_arg = 2;
3681 while (*(args[cur_arg])) {
3682 if (!strcmp(args[cur_arg], "except")) {
3683 /* suboption except - needs additional argument for it */
3684 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3685 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3686 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003689 }
3690 /* flush useless bits */
3691 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003692 cur_arg += 2;
3693 } else if (!strcmp(args[cur_arg], "header")) {
3694 /* suboption header - needs additional argument for it */
3695 if (*(args[cur_arg+1]) == 0) {
3696 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3697 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003700 }
3701 free(curproxy->fwdfor_hdr_name);
3702 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3703 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3704 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003705 } else if (!strcmp(args[cur_arg], "if-none")) {
3706 curproxy->options &= ~PR_O_FF_ALWAYS;
3707 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003708 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003709 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003710 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003711 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003714 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003715 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003716 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003717 else if (!strcmp(args[1], "originalto")) {
3718 int cur_arg;
3719
3720 /* insert x-original-to field, but not for the IP address listed as an except.
3721 * set default options (ie: bitfield, header name, etc)
3722 */
3723
3724 curproxy->options |= PR_O_ORGTO;
3725
3726 free(curproxy->orgto_hdr_name);
3727 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3728 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3729
Willy Tarreau87cf5142011-08-19 22:57:24 +02003730 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003731 cur_arg = 2;
3732 while (*(args[cur_arg])) {
3733 if (!strcmp(args[cur_arg], "except")) {
3734 /* suboption except - needs additional argument for it */
3735 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3736 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3737 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003740 }
3741 /* flush useless bits */
3742 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3743 cur_arg += 2;
3744 } else if (!strcmp(args[cur_arg], "header")) {
3745 /* suboption header - needs additional argument for it */
3746 if (*(args[cur_arg+1]) == 0) {
3747 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3748 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003751 }
3752 free(curproxy->orgto_hdr_name);
3753 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3754 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3755 cur_arg += 2;
3756 } else {
3757 /* unknown suboption - catchall */
3758 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3759 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003762 }
3763 } /* end while loop */
3764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 else {
3766 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
Willy Tarreau93893792009-07-23 13:19:11 +02003770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003772 else if (!strcmp(args[0], "default_backend")) {
3773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003775
3776 if (*(args[1]) == 0) {
3777 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003780 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003781 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003782 curproxy->defbe.name = strdup(args[1]);
3783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003788 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 /* enable reconnections to dispatch */
3792 curproxy->options |= PR_O_REDISP;
3793 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003794 else if (!strcmp(args[0], "http-check")) {
3795 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003797
3798 if (strcmp(args[1], "disable-on-404") == 0) {
3799 /* enable a graceful server shutdown on an HTTP 404 response */
3800 curproxy->options |= PR_O_DISABLE404;
3801 }
Willy Tarreauef781042010-01-27 11:53:01 +01003802 else if (strcmp(args[1], "send-state") == 0) {
3803 /* enable emission of the apparent state of a server in HTTP checks */
3804 curproxy->options2 |= PR_O2_CHK_SNDST;
3805 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003806 else if (strcmp(args[1], "expect") == 0) {
3807 const char *ptr_arg;
3808 int cur_arg;
3809
3810 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3811 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815
3816 cur_arg = 2;
3817 /* consider exclamation marks, sole or at the beginning of a word */
3818 while (*(ptr_arg = args[cur_arg])) {
3819 while (*ptr_arg == '!') {
3820 curproxy->options2 ^= PR_O2_EXP_INV;
3821 ptr_arg++;
3822 }
3823 if (*ptr_arg)
3824 break;
3825 cur_arg++;
3826 }
3827 /* now ptr_arg points to the beginning of a word past any possible
3828 * exclamation mark, and cur_arg is the argument which holds this word.
3829 */
3830 if (strcmp(ptr_arg, "status") == 0) {
3831 if (!*(args[cur_arg + 1])) {
3832 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3833 file, linenum, args[0], args[1], ptr_arg);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003838 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003839 curproxy->expect_str = strdup(args[cur_arg + 1]);
3840 }
3841 else if (strcmp(ptr_arg, "string") == 0) {
3842 if (!*(args[cur_arg + 1])) {
3843 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3844 file, linenum, args[0], args[1], ptr_arg);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003849 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003850 curproxy->expect_str = strdup(args[cur_arg + 1]);
3851 }
3852 else if (strcmp(ptr_arg, "rstatus") == 0) {
3853 if (!*(args[cur_arg + 1])) {
3854 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3855 file, linenum, args[0], args[1], ptr_arg);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003860 free(curproxy->expect_str);
3861 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3862 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003863 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3864 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3865 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3866 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 }
3871 else if (strcmp(ptr_arg, "rstring") == 0) {
3872 if (!*(args[cur_arg + 1])) {
3873 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3874 file, linenum, args[0], args[1], ptr_arg);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003879 free(curproxy->expect_str);
3880 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3881 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003882 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3883 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3884 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3885 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 }
3890 else {
3891 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3892 file, linenum, args[0], args[1], ptr_arg);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003897 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003898 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 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003901 }
3902 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003903 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003904 if (curproxy == &defproxy) {
3905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003908 }
3909
Willy Tarreaub80c2302007-11-30 20:51:32 +01003910 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003912
3913 if (strcmp(args[1], "fail") == 0) {
3914 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003915 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003916 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3917 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003920 }
3921
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003922 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3923 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3924 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003927 }
3928 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3929 }
3930 else {
3931 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003934 }
3935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936#ifdef TPROXY
3937 else if (!strcmp(args[0], "transparent")) {
3938 /* enable transparent proxy connections */
3939 curproxy->options |= PR_O_TRANSP;
3940 }
3941#endif
3942 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (*(args[1]) == 0) {
3947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
3951 curproxy->maxconn = atol(args[1]);
3952 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003953 else if (!strcmp(args[0], "backlog")) { /* backlog */
3954 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003956
3957 if (*(args[1]) == 0) {
3958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003961 }
3962 curproxy->backlog = atol(args[1]);
3963 }
Willy Tarreau86034312006-12-29 00:10:33 +01003964 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003967
Willy Tarreau86034312006-12-29 00:10:33 +01003968 if (*(args[1]) == 0) {
3969 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003972 }
3973 curproxy->fullconn = atol(args[1]);
3974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3976 if (*(args[1]) == 0) {
3977 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003981 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3982 if (err) {
3983 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3984 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003987 }
3988 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 }
3990 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003991 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 if (curproxy == &defproxy) {
3993 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003997 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003999
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 if (strchr(args[1], ':') == NULL) {
4001 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004005 sk = str2sa(args[1]);
4006 if (!sk) {
4007 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004012 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
4014 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004015 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004018 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4019 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004024 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4026 err_code |= ERR_WARN;
4027
4028 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4029 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4030 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4031 }
4032 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4033 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4034 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4035 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004036 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4037 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4038 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4039 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004040 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004041 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 char *rport, *raddr;
4049 short realport = 0;
4050 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004057 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059
4060 if (!*args[2]) {
4061 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004066
4067 err = invalid_char(args[1]);
4068 if (err) {
4069 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4070 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004073 }
4074
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004075 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004076 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004077
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004078 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4079 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4080 err_code |= ERR_ALERT | ERR_ABORT;
4081 goto out;
4082 }
4083
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084 /* the servers are linked backwards first */
4085 newsrv->next = curproxy->srv;
4086 curproxy->srv = newsrv;
4087 newsrv->proxy = curproxy;
4088 newsrv->conf.file = file;
4089 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090
Simon Hormanaf514952011-06-21 14:34:57 +09004091 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 LIST_INIT(&newsrv->pendconns);
4093 do_check = 0;
4094 newsrv->state = SRV_RUNNING; /* early server setup */
4095 newsrv->last_change = now.tv_sec;
4096 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004099 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 * - IP: => port=+0, relative
4101 * - IP:N => port=N, absolute
4102 * - IP:+N => port=+N, relative
4103 * - IP:-N => port=-N, relative
4104 */
4105 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004106 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004107 if (rport) {
4108 *rport++ = 0;
4109 realport = atol(rport);
4110 if (!isdigit((unsigned char)*rport))
4111 newsrv->state |= SRV_MAPPORTS;
4112 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114
Willy Tarreaufab5a432011-03-04 15:31:53 +01004115 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004117 if (!sk) {
4118 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
4122 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004123 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004124 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004125
4126 if (!sk) {
4127 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4128 file, linenum, newsrv->addr.ss_family, args[2]);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004132 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004133
4134 newsrv->check_port = curproxy->defsrv.check_port;
4135 newsrv->inter = curproxy->defsrv.inter;
4136 newsrv->fastinter = curproxy->defsrv.fastinter;
4137 newsrv->downinter = curproxy->defsrv.downinter;
4138 newsrv->rise = curproxy->defsrv.rise;
4139 newsrv->fall = curproxy->defsrv.fall;
4140 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4141 newsrv->minconn = curproxy->defsrv.minconn;
4142 newsrv->maxconn = curproxy->defsrv.maxconn;
4143 newsrv->slowstart = curproxy->defsrv.slowstart;
4144 newsrv->onerror = curproxy->defsrv.onerror;
4145 newsrv->consecutive_errors_limit
4146 = curproxy->defsrv.consecutive_errors_limit;
4147 newsrv->uweight = newsrv->iweight
4148 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 newsrv->curfd = -1; /* no health-check in progress */
4151 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 cur_arg = 3;
4154 } else {
4155 newsrv = &curproxy->defsrv;
4156 cur_arg = 1;
4157 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004158
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004160 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004161 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004162
4163 if (!*args[cur_arg + 1]) {
4164 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4165 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004168 }
4169
4170 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004171 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004172
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004173 if (newsrv->puid <= 0) {
4174 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004175 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004178 }
4179
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004180 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4181 if (node) {
4182 struct server *target = container_of(node, struct server, conf.id);
4183 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4184 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004189 cur_arg += 2;
4190 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004191 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 newsrv->cookie = strdup(args[cur_arg + 1]);
4193 newsrv->cklen = strlen(args[cur_arg + 1]);
4194 cur_arg += 2;
4195 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004196 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004197 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4198 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4199 cur_arg += 2;
4200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004202 if (!*args[cur_arg + 1]) {
4203 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4204 file, linenum, args[cur_arg]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 }
4208
Willy Tarreaubaaee002006-06-26 02:48:02 +02004209 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004210 if (newsrv->rise <= 0) {
4211 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4212 file, linenum, args[cur_arg]);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216
Willy Tarreau96839092010-03-29 10:02:24 +02004217 if (newsrv->health)
4218 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 cur_arg += 2;
4220 }
4221 else if (!strcmp(args[cur_arg], "fall")) {
4222 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004223
4224 if (!*args[cur_arg + 1]) {
4225 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4226 file, linenum, args[cur_arg]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
4231 if (newsrv->fall <= 0) {
4232 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4233 file, linenum, args[cur_arg]);
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
4236 }
4237
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238 cur_arg += 2;
4239 }
4240 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004241 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4242 if (err) {
4243 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4244 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004247 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004248 if (val <= 0) {
4249 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4250 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004253 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004254 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 cur_arg += 2;
4256 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004257 else if (!strcmp(args[cur_arg], "fastinter")) {
4258 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4259 if (err) {
4260 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4261 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004264 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004265 if (val <= 0) {
4266 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4267 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004270 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004271 newsrv->fastinter = val;
4272 cur_arg += 2;
4273 }
4274 else if (!strcmp(args[cur_arg], "downinter")) {
4275 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4276 if (err) {
4277 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4278 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004281 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004282 if (val <= 0) {
4283 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4284 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004287 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004288 newsrv->downinter = val;
4289 cur_arg += 2;
4290 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004291 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004292 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004293 if (!sk) {
4294 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004299 cur_arg += 2;
4300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 else if (!strcmp(args[cur_arg], "port")) {
4302 newsrv->check_port = atol(args[cur_arg + 1]);
4303 cur_arg += 2;
4304 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004305 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 newsrv->state |= SRV_BACKUP;
4307 cur_arg ++;
4308 }
Simon Hormanfa461682011-06-25 09:39:49 +09004309 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4310 newsrv->state |= SRV_NON_STICK;
4311 cur_arg ++;
4312 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004313 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4314 newsrv->state |= SRV_SEND_PROXY;
4315 cur_arg ++;
4316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 else if (!strcmp(args[cur_arg], "weight")) {
4318 int w;
4319 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004320 if (w < 0 || w > 256) {
4321 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004326 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 cur_arg += 2;
4328 }
4329 else if (!strcmp(args[cur_arg], "minconn")) {
4330 newsrv->minconn = atol(args[cur_arg + 1]);
4331 cur_arg += 2;
4332 }
4333 else if (!strcmp(args[cur_arg], "maxconn")) {
4334 newsrv->maxconn = atol(args[cur_arg + 1]);
4335 cur_arg += 2;
4336 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004337 else if (!strcmp(args[cur_arg], "maxqueue")) {
4338 newsrv->maxqueue = atol(args[cur_arg + 1]);
4339 cur_arg += 2;
4340 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004341 else if (!strcmp(args[cur_arg], "slowstart")) {
4342 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004343 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004344 if (err) {
4345 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4346 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004349 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004350 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004351 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4352 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004355 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004356 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004357 cur_arg += 2;
4358 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004359 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004360
4361 if (!*args[cur_arg + 1]) {
4362 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4363 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004366 }
4367
4368 newsrv->trackit = strdup(args[cur_arg + 1]);
4369
4370 cur_arg += 2;
4371 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004372 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004373 global.maxsock++;
4374 do_check = 1;
4375 cur_arg += 1;
4376 }
Willy Tarreau96839092010-03-29 10:02:24 +02004377 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4378 newsrv->state |= SRV_MAINTAIN;
4379 newsrv->state &= ~SRV_RUNNING;
4380 newsrv->health = 0;
4381 cur_arg += 1;
4382 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004383 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004384 if (!strcmp(args[cur_arg + 1], "none"))
4385 newsrv->observe = HANA_OBS_NONE;
4386 else if (!strcmp(args[cur_arg + 1], "layer4"))
4387 newsrv->observe = HANA_OBS_LAYER4;
4388 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4389 if (curproxy->mode != PR_MODE_HTTP) {
4390 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4391 file, linenum, args[cur_arg + 1]);
4392 err_code |= ERR_ALERT;
4393 }
4394 newsrv->observe = HANA_OBS_LAYER7;
4395 }
4396 else {
4397 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004398 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004399 file, linenum, args[cur_arg], args[cur_arg + 1]);
4400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
4402 }
4403
4404 cur_arg += 2;
4405 }
4406 else if (!strcmp(args[cur_arg], "on-error")) {
4407 if (!strcmp(args[cur_arg + 1], "fastinter"))
4408 newsrv->onerror = HANA_ONERR_FASTINTER;
4409 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4410 newsrv->onerror = HANA_ONERR_FAILCHK;
4411 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4412 newsrv->onerror = HANA_ONERR_SUDDTH;
4413 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4414 newsrv->onerror = HANA_ONERR_MARKDWN;
4415 else {
4416 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004417 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004418 file, linenum, args[cur_arg], args[cur_arg + 1]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422
4423 cur_arg += 2;
4424 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004425 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4426 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4427 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4428 else {
4429 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4430 file, linenum, args[cur_arg], args[cur_arg + 1]);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
4434
4435 cur_arg += 2;
4436 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004437 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4438 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4439 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4440 else {
4441 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4442 file, linenum, args[cur_arg], args[cur_arg + 1]);
4443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
4445 }
4446
4447 cur_arg += 2;
4448 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004449 else if (!strcmp(args[cur_arg], "error-limit")) {
4450 if (!*args[cur_arg + 1]) {
4451 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4452 file, linenum, args[cur_arg]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
4456
4457 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4458
4459 if (newsrv->consecutive_errors_limit <= 0) {
4460 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4461 file, linenum, args[cur_arg]);
4462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
4464 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004465 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004466 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004467 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004468 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004469 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004470
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004472#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004473 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004474 file, linenum, "source", "usesrc");
4475#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004476 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004478#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 }
4482 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004483 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4484 if (!sk) {
4485 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
4488 }
4489 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004490
4491 if (port_low != port_high) {
4492 int i;
4493 if (port_low <= 0 || port_low > 65535 ||
4494 port_high <= 0 || port_high > 65535 ||
4495 port_low > port_high) {
4496 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4497 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004500 }
4501 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4502 for (i = 0; i < newsrv->sport_range->size; i++)
4503 newsrv->sport_range->ports[i] = port_low + i;
4504 }
4505
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004507 while (*(args[cur_arg])) {
4508 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004509#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4510#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004511 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4512 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4513 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004516 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004517#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004518 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004519 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004523 }
4524 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004525 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004526 newsrv->state |= SRV_TPROXY_CLI;
4527 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004528 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004530 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4531 char *name, *end;
4532
4533 name = args[cur_arg+1] + 7;
4534 while (isspace(*name))
4535 name++;
4536
4537 end = name;
4538 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4539 end++;
4540
4541 newsrv->state &= ~SRV_TPROXY_MASK;
4542 newsrv->state |= SRV_TPROXY_DYN;
4543 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4544 newsrv->bind_hdr_len = end - name;
4545 memcpy(newsrv->bind_hdr_name, name, end - name);
4546 newsrv->bind_hdr_name[end-name] = '\0';
4547 newsrv->bind_hdr_occ = -1;
4548
4549 /* now look for an occurrence number */
4550 while (isspace(*end))
4551 end++;
4552 if (*end == ',') {
4553 end++;
4554 name = end;
4555 if (*end == '-')
4556 end++;
4557 while (isdigit(*end))
4558 end++;
4559 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4560 }
4561
4562 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4563 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4564 " occurrences values smaller than %d.\n",
4565 file, linenum, MAX_HDR_HISTORY);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004569 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004570 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004571 if (!sk) {
4572 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004577 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004578 }
4579 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004580#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004581 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004582#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004583 cur_arg += 2;
4584 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004585#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004586 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004587 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004590#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4591 } /* "usesrc" */
4592
4593 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4594#ifdef SO_BINDTODEVICE
4595 if (!*args[cur_arg + 1]) {
4596 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004600 }
4601 if (newsrv->iface_name)
4602 free(newsrv->iface_name);
4603
4604 newsrv->iface_name = strdup(args[cur_arg + 1]);
4605 newsrv->iface_len = strlen(newsrv->iface_name);
4606 global.last_checks |= LSTCHK_NETADM;
4607#else
4608 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4609 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004612#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004613 cur_arg += 2;
4614 continue;
4615 }
4616 /* this keyword in not an option of "source" */
4617 break;
4618 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004620 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004621 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4622 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004626 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004627 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004628 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 file, linenum, newsrv->id);
4630 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004631 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004632 file, linenum);
4633
Willy Tarreau93893792009-07-23 13:19:11 +02004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 }
4637 }
4638
4639 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004640 if (newsrv->trackit) {
4641 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4642 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004645 }
4646
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004647 /* try to get the port from check_addr if check_port not set */
4648 if (!newsrv->check_port)
4649 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004650
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4652 newsrv->check_port = realport; /* by default */
4653 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004654 /* not yet valid, because no port was set on
4655 * the server either. We'll check if we have
4656 * a known port on the first listener.
4657 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004658 struct listener *l = curproxy->listen;
4659 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4660 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004661 }
4662 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4664 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004667 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004668
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004669 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004670 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004671 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4672 err_code |= ERR_ALERT | ERR_ABORT;
4673 goto out;
4674 }
4675
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004676 /* Allocate buffer for partial check results... */
4677 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4678 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4679 err_code |= ERR_ALERT | ERR_ABORT;
4680 goto out;
4681 }
4682
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004683 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 newsrv->state |= SRV_CHECKED;
4685 }
4686
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004687 if (!defsrv) {
4688 if (newsrv->state & SRV_BACKUP)
4689 curproxy->srv_bck++;
4690 else
4691 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004692
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004693 newsrv->prev_state = newsrv->state;
4694 }
William Lallemanda73203e2012-03-12 12:48:57 +01004695 }
4696
4697 else if (strcmp(args[0], "unique-id-format") == 0) {
4698 if (!*(args[1])) {
4699 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
4702 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004703 free(curproxy->uniqueid_format_string);
4704 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004705 }
William Lallemanda73203e2012-03-12 12:48:57 +01004706
4707 else if (strcmp(args[0], "unique-id-header") == 0) {
4708 if (!*(args[1])) {
4709 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
4712 }
4713 free(curproxy->header_unique_id);
4714 curproxy->header_unique_id = strdup(args[1]);
4715 }
4716
William Lallemand723b73a2012-02-08 16:37:49 +01004717 else if (strcmp(args[0], "log-format") == 0) {
4718 if (!*(args[1])) {
4719 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
4722 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004723
4724 if (curproxy->logformat_string != default_http_log_format &&
4725 curproxy->logformat_string != default_tcp_log_format &&
4726 curproxy->logformat_string != clf_http_log_format)
4727 free(curproxy->logformat_string);
4728 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
William Lallemand723b73a2012-02-08 16:37:49 +01004730
William Lallemand0f99e342011-10-12 17:50:54 +02004731 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4732 /* delete previous herited or defined syslog servers */
4733 struct logsrv *back;
4734
4735 if (*(args[1]) != 0) {
4736 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
4740
William Lallemand723b73a2012-02-08 16:37:49 +01004741 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4742 LIST_DEL(&tmplogsrv->list);
4743 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004744 }
4745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004747 struct logsrv *logsrv;
4748
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004750 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004751 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004752 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004753 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004754 LIST_INIT(&node->list);
4755 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004759
4760 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761
William Lallemand0f99e342011-10-12 17:50:54 +02004762 logsrv->facility = get_log_facility(args[2]);
4763 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
4767
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
4769
William Lallemand0f99e342011-10-12 17:50:54 +02004770 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004772 logsrv->level = get_log_level(args[3]);
4773 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
4779 }
4780
William Lallemand0f99e342011-10-12 17:50:54 +02004781 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004782 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004783 logsrv->minlvl = get_log_level(args[4]);
4784 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004785 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004789 }
4790 }
4791
Robert Tsai81ae1952007-12-05 10:47:29 +01004792 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004793 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004794 if (!sk) {
4795 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004796 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
William Lallemand0f99e342011-10-12 17:50:54 +02004800 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004801 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004802 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004803 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004804 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
William Lallemand0f99e342011-10-12 17:50:54 +02004808 logsrv->addr = *sk;
4809 if (!get_host_port(&logsrv->addr))
4810 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 }
William Lallemand0f99e342011-10-12 17:50:54 +02004812
4813 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
4815 else {
4816 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4817 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
4821 }
4822 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004823 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004824 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825
Willy Tarreau977b8e42006-12-29 14:19:17 +01004826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004828
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004830 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4831 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004835
4836 /* we must first clear any optional default setting */
4837 curproxy->options &= ~PR_O_TPXY_MASK;
4838 free(curproxy->iface_name);
4839 curproxy->iface_name = NULL;
4840 curproxy->iface_len = 0;
4841
Willy Tarreaud5191e72010-02-09 20:50:45 +01004842 sk = str2sa(args[1]);
4843 if (!sk) {
4844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004850
4851 cur_arg = 2;
4852 while (*(args[cur_arg])) {
4853 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004854#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4855#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004856 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4857 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4858 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004861 }
4862#endif
4863 if (!*args[cur_arg + 1]) {
4864 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4865 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 }
4869
4870 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004871 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004872 curproxy->options |= PR_O_TPXY_CLI;
4873 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004874 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004876 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4877 char *name, *end;
4878
4879 name = args[cur_arg+1] + 7;
4880 while (isspace(*name))
4881 name++;
4882
4883 end = name;
4884 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4885 end++;
4886
4887 curproxy->options &= ~PR_O_TPXY_MASK;
4888 curproxy->options |= PR_O_TPXY_DYN;
4889 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4890 curproxy->bind_hdr_len = end - name;
4891 memcpy(curproxy->bind_hdr_name, name, end - name);
4892 curproxy->bind_hdr_name[end-name] = '\0';
4893 curproxy->bind_hdr_occ = -1;
4894
4895 /* now look for an occurrence number */
4896 while (isspace(*end))
4897 end++;
4898 if (*end == ',') {
4899 end++;
4900 name = end;
4901 if (*end == '-')
4902 end++;
4903 while (isdigit(*end))
4904 end++;
4905 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4906 }
4907
4908 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4909 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4910 " occurrences values smaller than %d.\n",
4911 file, linenum, MAX_HDR_HISTORY);
4912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004915 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004916 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004917 if (!sk) {
4918 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
4921 }
4922 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 }
4925 global.last_checks |= LSTCHK_NETADM;
4926#if !defined(CONFIG_HAP_LINUX_TPROXY)
4927 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004928#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004929#else /* no TPROXY support */
4930 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004931 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_ALERT | ERR_FATAL;
4933 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004934#endif
4935 cur_arg += 2;
4936 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004937 }
4938
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004939 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4940#ifdef SO_BINDTODEVICE
4941 if (!*args[cur_arg + 1]) {
4942 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004946 }
4947 if (curproxy->iface_name)
4948 free(curproxy->iface_name);
4949
4950 curproxy->iface_name = strdup(args[cur_arg + 1]);
4951 curproxy->iface_len = strlen(curproxy->iface_name);
4952 global.last_checks |= LSTCHK_NETADM;
4953#else
4954 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4955 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004958#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959 cur_arg += 2;
4960 continue;
4961 }
4962 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4963 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004968 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4969 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4970 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981
4982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], args[2], (const char **)args+3);
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], "reqdel")) { /* delete request header from a regex */
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_REMOVE, 0,
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], "reqdeny")) { /* deny a request if a header matches this regex */
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_DENY, 0,
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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 0,
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 }
5009 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
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 Tarreaubaaee002006-06-26 02:48:02 +02005015 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005016 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005018 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005019 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005021 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005022 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005023 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005025 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005029 }
5030 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005032 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005033 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005035 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044
5045 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005046 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005047 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
5051 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005053 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005054 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
5058 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005060 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005061 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005067 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005074 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005079 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005081 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005082 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005084 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005087 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005088
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 if (curproxy == &defproxy) {
5090 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005094 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 if (*(args[1]) == 0) {
5098 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005102
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005103 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005104 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5105 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5106 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5111 }
5112 else if (*args[2]) {
5113 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5114 file, linenum, args[0], args[2]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005119 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005120 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005121 wl->s = strdup(args[1]);
5122 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005123 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5128 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005132
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005134 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005135 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005136 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
5139 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005141 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005142 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
5146 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
5153 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5156 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005163 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005169 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005170 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005177 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005182 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005183
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 if (curproxy == &defproxy) {
5185 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005189 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 if (*(args[1]) == 0) {
5193 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
5197
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005198 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005199 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5200 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5201 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205 err_code |= warnif_cond_requires_req(cond, file, linenum);
5206 }
5207 else if (*args[2]) {
5208 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5209 file, linenum, args[0], args[2]);
5210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
5212 }
5213
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005214 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005215 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005216 wl->s = strdup(args[1]);
5217 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
5219 else if (!strcmp(args[0], "errorloc") ||
5220 !strcmp(args[0], "errorloc302") ||
5221 !strcmp(args[0], "errorloc303")) { /* error location */
5222 int errnum, errlen;
5223 char *err;
5224
Willy Tarreau977b8e42006-12-29 14:19:17 +01005225 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005227
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005229 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233
5234 errnum = atol(args[1]);
5235 if (!strcmp(args[0], "errorloc303")) {
5236 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5237 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5238 } else {
5239 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5240 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5241 }
5242
Willy Tarreau0f772532006-12-23 20:51:41 +01005243 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5244 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005245 chunk_destroy(&curproxy->errmsg[rc]);
5246 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005247 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005250
5251 if (rc >= HTTP_ERR_SIZE) {
5252 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5253 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 free(err);
5255 }
5256 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005257 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5258 int errnum, errlen, fd;
5259 char *err;
5260 struct stat stat;
5261
5262 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005264
5265 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005266 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005269 }
5270
5271 fd = open(args[2], O_RDONLY);
5272 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5273 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5274 file, linenum, args[2], args[1]);
5275 if (fd >= 0)
5276 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005279 }
5280
Willy Tarreau27a674e2009-08-17 07:23:33 +02005281 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005282 errlen = stat.st_size;
5283 } else {
5284 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005285 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005287 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005288 }
5289
5290 err = malloc(errlen); /* malloc() must succeed during parsing */
5291 errnum = read(fd, err, errlen);
5292 if (errnum != errlen) {
5293 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5294 file, linenum, args[2], args[1]);
5295 close(fd);
5296 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005297 err_code |= ERR_ALERT | ERR_FATAL;
5298 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005299 }
5300 close(fd);
5301
5302 errnum = atol(args[1]);
5303 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5304 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005305 chunk_destroy(&curproxy->errmsg[rc]);
5306 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005307 break;
5308 }
5309 }
5310
5311 if (rc >= HTTP_ERR_SIZE) {
5312 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5313 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005314 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005315 free(err);
5316 }
5317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005319 struct cfg_kw_list *kwl;
5320 int index;
5321
5322 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5323 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5324 if (kwl->kw[index].section != CFG_LISTEN)
5325 continue;
5326 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5327 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005328 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005329 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005330 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005331 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005332 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005335 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005336 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005337 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_WARN;
5339 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005340 }
Willy Tarreau93893792009-07-23 13:19:11 +02005341 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005342 }
5343 }
5344 }
5345
Willy Tarreau6daf3432008-01-22 16:44:08 +01005346 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
Willy Tarreau93893792009-07-23 13:19:11 +02005350 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005351 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005352 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353}
5354
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005355int
5356cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5357{
5358
5359 int err_code = 0;
5360 const char *err;
5361
5362 if (!strcmp(args[0], "userlist")) { /* new userlist */
5363 struct userlist *newul;
5364
5365 if (!*args[1]) {
5366 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5367 file, linenum, args[0]);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371
5372 err = invalid_char(args[1]);
5373 if (err) {
5374 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5375 file, linenum, *err, args[0], args[1]);
5376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
5378 }
5379
5380 for (newul = userlist; newul; newul = newul->next)
5381 if (!strcmp(newul->name, args[1])) {
5382 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5383 file, linenum, args[1]);
5384 err_code |= ERR_WARN;
5385 goto out;
5386 }
5387
5388 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5389 if (!newul) {
5390 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5391 err_code |= ERR_ALERT | ERR_ABORT;
5392 goto out;
5393 }
5394
5395 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5396 newul->name = strdup(args[1]);
5397
5398 if (!newul->groupusers | !newul->name) {
5399 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5400 err_code |= ERR_ALERT | ERR_ABORT;
5401 goto out;
5402 }
5403
5404 newul->next = userlist;
5405 userlist = newul;
5406
5407 } else if (!strcmp(args[0], "group")) { /* new group */
5408 int cur_arg, i;
5409 const char *err;
5410
5411 if (!*args[1]) {
5412 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5413 file, linenum, args[0]);
5414 err_code |= ERR_ALERT | ERR_FATAL;
5415 goto out;
5416 }
5417
5418 err = invalid_char(args[1]);
5419 if (err) {
5420 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5421 file, linenum, *err, args[0], args[1]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
5425
5426 for(i = 0; i < userlist->grpcnt; i++)
5427 if (!strcmp(userlist->groups[i], args[1])) {
5428 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5429 file, linenum, args[1], userlist->name);
5430 err_code |= ERR_ALERT;
5431 goto out;
5432 }
5433
5434 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5435 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5436 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5437 err_code |= ERR_ALERT | ERR_FATAL;
5438 goto out;
5439 }
5440
5441 cur_arg = 2;
5442
5443 while (*args[cur_arg]) {
5444 if (!strcmp(args[cur_arg], "users")) {
5445 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5446 cur_arg += 2;
5447 continue;
5448 } else {
5449 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5450 file, linenum, args[0]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 }
5455
5456 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5457 } else if (!strcmp(args[0], "user")) { /* new user */
5458 struct auth_users *newuser;
5459 int cur_arg;
5460
5461 if (!*args[1]) {
5462 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5463 file, linenum, args[0]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467
5468 for (newuser = userlist->users; newuser; newuser = newuser->next)
5469 if (!strcmp(newuser->user, args[1])) {
5470 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5471 file, linenum, args[1], userlist->name);
5472 err_code |= ERR_ALERT;
5473 goto out;
5474 }
5475
5476 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5477 if (!newuser) {
5478 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5479 err_code |= ERR_ALERT | ERR_ABORT;
5480 goto out;
5481 }
5482
5483 newuser->user = strdup(args[1]);
5484
5485 newuser->next = userlist->users;
5486 userlist->users = newuser;
5487
5488 cur_arg = 2;
5489
5490 while (*args[cur_arg]) {
5491 if (!strcmp(args[cur_arg], "password")) {
5492#ifndef CONFIG_HAP_CRYPT
5493 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5494 file, linenum);
5495 err_code |= ERR_ALERT;
5496#endif
5497 newuser->pass = strdup(args[cur_arg + 1]);
5498 cur_arg += 2;
5499 continue;
5500 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5501 newuser->pass = strdup(args[cur_arg + 1]);
5502 newuser->flags |= AU_O_INSECURE;
5503 cur_arg += 2;
5504 continue;
5505 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005506 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005507 cur_arg += 2;
5508 continue;
5509 } else {
5510 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5511 file, linenum, args[0]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 }
5516 } else {
5517 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 }
5520
5521out:
5522 return err_code;
5523}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524
5525/*
5526 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005527 * Returns the error code, 0 if OK, or any combination of :
5528 * - ERR_ABORT: must abort ASAP
5529 * - ERR_FATAL: we can continue parsing but not start the service
5530 * - ERR_WARN: a warning has been emitted
5531 * - ERR_ALERT: an alert has been emitted
5532 * Only the two first ones can stop processing, the two others are just
5533 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005535int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005537 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 FILE *f;
5539 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005541 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 if ((f=fopen(file,"r")) == NULL)
5544 return -1;
5545
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005546 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005547 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005548 char *end;
5549 char *args[MAX_LINE_ARGS + 1];
5550 char *line = thisline;
5551
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 linenum++;
5553
5554 end = line + strlen(line);
5555
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005556 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5557 /* Check if we reached the limit and the last char is not \n.
5558 * Watch out for the last line without the terminating '\n'!
5559 */
5560 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005561 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005562 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005563 }
5564
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005566 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 line++;
5568
5569 arg = 0;
5570 args[arg] = line;
5571
5572 while (*line && arg < MAX_LINE_ARGS) {
5573 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5574 * C equivalent value. Other combinations left unchanged (eg: \1).
5575 */
5576 if (*line == '\\') {
5577 int skip = 0;
5578 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5579 *line = line[1];
5580 skip = 1;
5581 }
5582 else if (line[1] == 'r') {
5583 *line = '\r';
5584 skip = 1;
5585 }
5586 else if (line[1] == 'n') {
5587 *line = '\n';
5588 skip = 1;
5589 }
5590 else if (line[1] == 't') {
5591 *line = '\t';
5592 skip = 1;
5593 }
5594 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005595 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 unsigned char hex1, hex2;
5597 hex1 = toupper(line[2]) - '0';
5598 hex2 = toupper(line[3]) - '0';
5599 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5600 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5601 *line = (hex1<<4) + hex2;
5602 skip = 3;
5603 }
5604 else {
5605 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005606 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 }
5608 }
5609 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005610 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 end -= skip;
5612 }
5613 line++;
5614 }
5615 else if (*line == '#' || *line == '\n' || *line == '\r') {
5616 /* end of string, end of loop */
5617 *line = 0;
5618 break;
5619 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005620 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005622 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005623 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 line++;
5625 args[++arg] = line;
5626 }
5627 else {
5628 line++;
5629 }
5630 }
5631
5632 /* empty line */
5633 if (!**args)
5634 continue;
5635
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005636 if (*line) {
5637 /* we had to stop due to too many args.
5638 * Let's terminate the string, print the offending part then cut the
5639 * last arg.
5640 */
5641 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5642 line++;
5643 *line = '\0';
5644
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005645 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005646 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 args[arg] = line;
5649 }
5650
Willy Tarreau540abe42007-05-02 20:50:16 +02005651 /* zero out remaining args and ensure that at least one entry
5652 * is zeroed out.
5653 */
5654 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 args[arg] = line;
5656 }
5657
Willy Tarreau3842f002009-06-14 11:39:52 +02005658 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005659 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005660 char *tmp;
5661
Willy Tarreau3842f002009-06-14 11:39:52 +02005662 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005663 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005664 for (arg=0; *args[arg+1]; arg++)
5665 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005666 *tmp = '\0'; // fix the next arg to \0
5667 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005668 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005669 else if (!strcmp(args[0], "default")) {
5670 kwm = KWM_DEF;
5671 for (arg=0; *args[arg+1]; arg++)
5672 args[arg] = args[arg+1]; // shift args after inversion
5673 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005674
William Lallemand0f99e342011-10-12 17:50:54 +02005675 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5676 strcmp(args[0], "log") != 0) {
5677 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005679 }
5680
Willy Tarreau977b8e42006-12-29 14:19:17 +01005681 if (!strcmp(args[0], "listen") ||
5682 !strcmp(args[0], "frontend") ||
5683 !strcmp(args[0], "backend") ||
5684 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005685 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005687 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005688 cursection = strdup(args[0]);
5689 }
5690 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005692 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005693 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005694 }
5695 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005696 confsect = CFG_USERLIST;
5697 free(cursection);
5698 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005699 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005700 else if (!strcmp(args[0], "peers")) {
5701 confsect = CFG_PEERS;
5702 free(cursection);
5703 cursection = strdup(args[0]);
5704 }
5705
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 /* else it's a section keyword */
5707
5708 switch (confsect) {
5709 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 break;
5712 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005713 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005715 case CFG_USERLIST:
5716 err_code |= cfg_parse_users(file, linenum, args, kwm);
5717 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005718 case CFG_PEERS:
5719 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5720 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005722 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005725
5726 if (err_code & ERR_ABORT)
5727 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005729 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005730 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005732 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005733}
5734
Willy Tarreaubb925012009-07-23 13:36:36 +02005735/*
5736 * Returns the error code, 0 if OK, or any combination of :
5737 * - ERR_ABORT: must abort ASAP
5738 * - ERR_FATAL: we can continue parsing but not start the service
5739 * - ERR_WARN: a warning has been emitted
5740 * - ERR_ALERT: an alert has been emitted
5741 * Only the two first ones can stop processing, the two others are just
5742 * indicators.
5743 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005744int check_config_validity()
5745{
5746 int cfgerr = 0;
5747 struct proxy *curproxy = NULL;
5748 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005749 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005750 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005751 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752
5753 /*
5754 * Now, check for the integrity of all that we have collected.
5755 */
5756
5757 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005758 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005760 /* first, we will invert the proxy list order */
5761 curproxy = NULL;
5762 while (proxy) {
5763 struct proxy *next;
5764
5765 next = proxy->next;
5766 proxy->next = curproxy;
5767 curproxy = proxy;
5768 if (!next)
5769 break;
5770 proxy = next;
5771 }
5772
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005774 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005775 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005776 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005777 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005778 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005779 unsigned int next_id;
5780
5781 if (!curproxy->uuid) {
5782 /* proxy ID not set, use automatic numbering with first
5783 * spare entry starting with next_pxid.
5784 */
5785 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5786 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5787 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005788 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005789 next_pxid++;
5790
Willy Tarreau55ea7572007-06-17 19:56:27 +02005791
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005793 /* ensure we don't keep listeners uselessly bound */
5794 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 curproxy = curproxy->next;
5796 continue;
5797 }
5798
Willy Tarreauff01a212009-03-15 13:46:16 +01005799 switch (curproxy->mode) {
5800 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005801 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005802 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005803 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5804 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005805 cfgerr++;
5806 }
5807
5808 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005809 Warning("config : servers will be ignored for %s '%s'.\n",
5810 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005811 break;
5812
5813 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005814 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005815 break;
5816
5817 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005818 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005819 break;
5820 }
5821
5822 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005823 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5824 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 cfgerr++;
5826 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005827
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005828 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005829 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005830 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005831 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5832 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005833 cfgerr++;
5834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005836 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005837 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5838 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005839 cfgerr++;
5840 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005842 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005843 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5844 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005845 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005846 }
5847 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005848 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005849 /* If no LB algo is set in a backend, and we're not in
5850 * transparent mode, dispatch mode nor proxy mode, we
5851 * want to use balance roundrobin by default.
5852 */
5853 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5854 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 }
5856 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005857
Willy Tarreau1620ec32011-08-06 17:05:02 +02005858 if (curproxy->options & PR_O_DISPATCH)
5859 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5860 else if (curproxy->options & PR_O_HTTP_PROXY)
5861 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5862 else if (curproxy->options & PR_O_TRANSP)
5863 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005864
Willy Tarreau1620ec32011-08-06 17:05:02 +02005865 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5866 if (curproxy->options & PR_O_DISABLE404) {
5867 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5868 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5869 err_code |= ERR_WARN;
5870 curproxy->options &= ~PR_O_DISABLE404;
5871 }
5872 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5873 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5874 "send-state", proxy_type_str(curproxy), curproxy->id);
5875 err_code |= ERR_WARN;
5876 curproxy->options &= ~PR_O2_CHK_SNDST;
5877 }
Willy Tarreauef781042010-01-27 11:53:01 +01005878 }
5879
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005880 /* if a default backend was specified, let's find it */
5881 if (curproxy->defbe.name) {
5882 struct proxy *target;
5883
Alex Williams96532db2009-11-01 21:27:13 -05005884 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005885 if (!target) {
5886 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5887 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005888 cfgerr++;
5889 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005890 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5891 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005892 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005893 } else {
5894 free(curproxy->defbe.name);
5895 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005896 /* we force the backend to be present on at least all of
5897 * the frontend's processes.
5898 */
5899 target->bind_proc = curproxy->bind_proc ?
5900 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005901
5902 /* Emit a warning if this proxy also has some servers */
5903 if (curproxy->srv) {
5904 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5905 curproxy->id);
5906 err_code |= ERR_WARN;
5907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 }
5910
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005911 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005912 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5913 /* map jump target for ACT_SETBE in req_rep chain */
5914 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005915 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005916 struct proxy *target;
5917
Willy Tarreaua496b602006-12-17 23:15:24 +01005918 if (exp->action != ACT_SETBE)
5919 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005920
Alex Williams96532db2009-11-01 21:27:13 -05005921 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005922 if (!target) {
5923 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5924 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005925 cfgerr++;
5926 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005927 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5928 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005929 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005930 } else {
5931 free((void *)exp->replace);
5932 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005933 /* we force the backend to be present on at least all of
5934 * the frontend's processes.
5935 */
5936 target->bind_proc = curproxy->bind_proc ?
5937 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005938 }
5939 }
5940 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005941
5942 /* find the target proxy for 'use_backend' rules */
5943 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005944 struct proxy *target;
5945
Alex Williams96532db2009-11-01 21:27:13 -05005946 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005947
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005948 if (!target) {
5949 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5950 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005951 cfgerr++;
5952 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005953 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5954 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005955 cfgerr++;
5956 } else {
5957 free((void *)rule->be.name);
5958 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005959 /* we force the backend to be present on at least all of
5960 * the frontend's processes.
5961 */
5962 target->bind_proc = curproxy->bind_proc ?
5963 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005964 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005965 }
5966
5967 /* find the target proxy for 'use_backend' rules */
5968 list_for_each_entry(srule, &curproxy->server_rules, list) {
5969 struct server *target = findserver(curproxy, srule->srv.name);
5970
5971 if (!target) {
5972 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5973 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5974 cfgerr++;
5975 continue;
5976 }
5977 free((void *)srule->srv.name);
5978 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005979 }
5980
Emeric Brunb982a3d2010-01-04 15:45:53 +01005981 /* find the target table for 'stick' rules */
5982 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5983 struct proxy *target;
5984
Emeric Brun1d33b292010-01-04 15:47:17 +01005985 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5986 if (mrule->flags & STK_IS_STORE)
5987 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5988
Emeric Brunb982a3d2010-01-04 15:45:53 +01005989 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005990 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005991 else
5992 target = curproxy;
5993
5994 if (!target) {
5995 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5996 curproxy->id, mrule->table.name);
5997 cfgerr++;
5998 }
5999 else if (target->table.size == 0) {
6000 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6001 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6002 cfgerr++;
6003 }
Willy Tarreau12785782012-04-27 21:37:17 +02006004 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6005 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006006 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6007 cfgerr++;
6008 }
6009 else {
6010 free((void *)mrule->table.name);
6011 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006012 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006013 }
6014 }
6015
6016 /* find the target table for 'store response' rules */
6017 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6018 struct proxy *target;
6019
Emeric Brun1d33b292010-01-04 15:47:17 +01006020 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6021
Emeric Brunb982a3d2010-01-04 15:45:53 +01006022 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006023 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006024 else
6025 target = curproxy;
6026
6027 if (!target) {
6028 Alert("Proxy '%s': unable to find store table '%s'.\n",
6029 curproxy->id, mrule->table.name);
6030 cfgerr++;
6031 }
6032 else if (target->table.size == 0) {
6033 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6034 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6035 cfgerr++;
6036 }
Willy Tarreau12785782012-04-27 21:37:17 +02006037 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6038 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006039 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6040 cfgerr++;
6041 }
6042 else {
6043 free((void *)mrule->table.name);
6044 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006045 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006046 }
6047 }
6048
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006049 /* find the target table for 'tcp-request' layer 4 rules */
6050 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6051 struct proxy *target;
6052
Willy Tarreau56123282010-08-06 19:06:56 +02006053 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006054 continue;
6055
6056 if (trule->act_prm.trk_ctr.table.n)
6057 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6058 else
6059 target = curproxy;
6060
6061 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006062 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6063 curproxy->id, trule->act_prm.trk_ctr.table.n,
6064 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006065 cfgerr++;
6066 }
6067 else if (target->table.size == 0) {
6068 Alert("Proxy '%s': table '%s' used but not configured.\n",
6069 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6070 cfgerr++;
6071 }
6072 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006073 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 +02006074 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6075 cfgerr++;
6076 }
6077 else {
6078 free(trule->act_prm.trk_ctr.table.n);
6079 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006080 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006081 * to pass a list of counters to track and allocate them right here using
6082 * stktable_alloc_data_type().
6083 */
6084 }
6085 }
6086
Willy Tarreaud1f96522010-08-03 19:34:32 +02006087 /* find the target table for 'tcp-request' layer 6 rules */
6088 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6089 struct proxy *target;
6090
Willy Tarreau56123282010-08-06 19:06:56 +02006091 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006092 continue;
6093
6094 if (trule->act_prm.trk_ctr.table.n)
6095 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6096 else
6097 target = curproxy;
6098
6099 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006100 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6101 curproxy->id, trule->act_prm.trk_ctr.table.n,
6102 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006103 cfgerr++;
6104 }
6105 else if (target->table.size == 0) {
6106 Alert("Proxy '%s': table '%s' used but not configured.\n",
6107 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6108 cfgerr++;
6109 }
6110 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006111 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 +02006112 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6113 cfgerr++;
6114 }
6115 else {
6116 free(trule->act_prm.trk_ctr.table.n);
6117 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006118 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006119 * to pass a list of counters to track and allocate them right here using
6120 * stktable_alloc_data_type().
6121 */
6122 }
6123 }
6124
Emeric Brun32da3c42010-09-23 18:39:19 +02006125 if (curproxy->table.peers.name) {
6126 struct peers *curpeers = peers;
6127
6128 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6129 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6130 free((void *)curproxy->table.peers.name);
6131 curproxy->table.peers.p = peers;
6132 break;
6133 }
6134 }
6135
6136 if (!curpeers) {
6137 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6138 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006139 free((void *)curproxy->table.peers.name);
6140 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006141 cfgerr++;
6142 }
6143 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006144 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6145 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006146 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006147 cfgerr++;
6148 }
6149 }
6150
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006151 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006152 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006153 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6154 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6155 "proxy", curproxy->id);
6156 cfgerr++;
6157 goto out_uri_auth_compat;
6158 }
6159
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006160 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006161 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006162 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006163 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006164
Willy Tarreau95fa4692010-02-01 13:05:50 +01006165 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6166 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006167
6168 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006169 uri_auth_compat_req[i++] = "realm";
6170 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6171 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006172
Willy Tarreau95fa4692010-02-01 13:05:50 +01006173 uri_auth_compat_req[i++] = "unless";
6174 uri_auth_compat_req[i++] = "{";
6175 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6176 uri_auth_compat_req[i++] = "}";
6177 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006178
Willy Tarreauff011f22011-01-06 17:51:27 +01006179 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6180 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006181 cfgerr++;
6182 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006183 }
6184
Willy Tarreauff011f22011-01-06 17:51:27 +01006185 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006186
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006187 if (curproxy->uri_auth->auth_realm) {
6188 free(curproxy->uri_auth->auth_realm);
6189 curproxy->uri_auth->auth_realm = NULL;
6190 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006191
6192 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006193 }
6194out_uri_auth_compat:
6195
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006196 cfgerr += acl_find_targets(curproxy);
6197
Willy Tarreau2738a142006-07-08 17:28:09 +02006198 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006199 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006200 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006201 (!curproxy->timeout.connect ||
6202 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006204 " | While not properly invalid, you will certainly encounter various problems\n"
6205 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006206 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006207 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006208 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006209 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006210
Willy Tarreau1fa31262007-12-03 00:36:16 +01006211 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6212 * We must still support older configurations, so let's find out whether those
6213 * parameters have been set or must be copied from contimeouts.
6214 */
6215 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006216 if (!curproxy->timeout.tarpit ||
6217 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006218 /* tarpit timeout not set. We search in the following order:
6219 * default.tarpit, curr.connect, default.connect.
6220 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006221 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006222 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006223 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006224 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006225 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006226 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006227 }
6228 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006229 (!curproxy->timeout.queue ||
6230 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006231 /* queue timeout not set. We search in the following order:
6232 * default.queue, curr.connect, default.connect.
6233 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006234 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006235 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006236 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006237 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006238 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006239 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006240 }
6241 }
6242
Willy Tarreau1620ec32011-08-06 17:05:02 +02006243 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006244 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6245 curproxy->check_req = (char *)malloc(curproxy->check_len);
6246 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006247 }
6248
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006249 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006250 if (curproxy->nb_req_cap) {
6251 if (curproxy->mode == PR_MODE_HTTP) {
6252 curproxy->req_cap_pool = create_pool("ptrcap",
6253 curproxy->nb_req_cap * sizeof(char *),
6254 MEM_F_SHARED);
6255 } else {
6256 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6257 proxy_type_str(curproxy), curproxy->id);
6258 err_code |= ERR_WARN;
6259 curproxy->to_log &= ~LW_REQHDR;
6260 curproxy->nb_req_cap = 0;
6261 }
6262 }
6263
6264 if (curproxy->nb_rsp_cap) {
6265 if (curproxy->mode == PR_MODE_HTTP) {
6266 curproxy->rsp_cap_pool = create_pool("ptrcap",
6267 curproxy->nb_rsp_cap * sizeof(char *),
6268 MEM_F_SHARED);
6269 } else {
6270 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6271 proxy_type_str(curproxy), curproxy->id);
6272 err_code |= ERR_WARN;
6273 curproxy->to_log &= ~LW_REQHDR;
6274 curproxy->nb_rsp_cap = 0;
6275 }
6276 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006277
Willy Tarreau196729e2012-05-31 19:30:26 +02006278 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006279 if (!(curproxy->cap & PR_CAP_FE)) {
6280 if (curproxy->logformat_string != default_http_log_format &&
6281 curproxy->logformat_string != default_tcp_log_format &&
6282 curproxy->logformat_string != clf_http_log_format)
6283 free(curproxy->logformat_string);
6284 curproxy->logformat_string = NULL;
6285 }
6286
Willy Tarreau196729e2012-05-31 19:30:26 +02006287 if (curproxy->logformat_string)
6288 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6289
6290 if (curproxy->uniqueid_format_string)
6291 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6292
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 /* first, we will invert the servers list order */
6294 newsrv = NULL;
6295 while (curproxy->srv) {
6296 struct server *next;
6297
6298 next = curproxy->srv->next;
6299 curproxy->srv->next = newsrv;
6300 newsrv = curproxy->srv;
6301 if (!next)
6302 break;
6303 curproxy->srv = next;
6304 }
6305
Willy Tarreaudd701652010-05-25 23:03:02 +02006306 /* assign automatic UIDs to servers which don't have one yet */
6307 next_id = 1;
6308 newsrv = curproxy->srv;
6309 while (newsrv != NULL) {
6310 if (!newsrv->puid) {
6311 /* server ID not set, use automatic numbering with first
6312 * spare entry starting with next_svid.
6313 */
6314 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6315 newsrv->conf.id.key = newsrv->puid = next_id;
6316 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6317 }
6318 next_id++;
6319 newsrv = newsrv->next;
6320 }
6321
Willy Tarreau20697042007-11-15 23:26:18 +01006322 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006323 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324
Willy Tarreau62c3be22012-01-20 13:12:32 +01006325 /*
6326 * If this server supports a maxconn parameter, it needs a dedicated
6327 * tasks to fill the emptied slots when a connection leaves.
6328 * Also, resolve deferred tracking dependency if needed.
6329 */
6330 newsrv = curproxy->srv;
6331 while (newsrv != NULL) {
6332 if (newsrv->minconn > newsrv->maxconn) {
6333 /* Only 'minconn' was specified, or it was higher than or equal
6334 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6335 * this will avoid further useless expensive computations.
6336 */
6337 newsrv->maxconn = newsrv->minconn;
6338 } else if (newsrv->maxconn && !newsrv->minconn) {
6339 /* minconn was not specified, so we set it to maxconn */
6340 newsrv->minconn = newsrv->maxconn;
6341 }
6342
6343 if (newsrv->trackit) {
6344 struct proxy *px;
6345 struct server *srv;
6346 char *pname, *sname;
6347
6348 pname = newsrv->trackit;
6349 sname = strrchr(pname, '/');
6350
6351 if (sname)
6352 *sname++ = '\0';
6353 else {
6354 sname = pname;
6355 pname = NULL;
6356 }
6357
6358 if (pname) {
6359 px = findproxy(pname, PR_CAP_BE);
6360 if (!px) {
6361 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6362 proxy_type_str(curproxy), curproxy->id,
6363 newsrv->id, pname);
6364 cfgerr++;
6365 goto next_srv;
6366 }
6367 } else
6368 px = curproxy;
6369
6370 srv = findserver(px, sname);
6371 if (!srv) {
6372 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6373 proxy_type_str(curproxy), curproxy->id,
6374 newsrv->id, sname);
6375 cfgerr++;
6376 goto next_srv;
6377 }
6378
6379 if (!(srv->state & SRV_CHECKED)) {
6380 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6381 "tracking as it does not have checks enabled.\n",
6382 proxy_type_str(curproxy), curproxy->id,
6383 newsrv->id, px->id, srv->id);
6384 cfgerr++;
6385 goto next_srv;
6386 }
6387
6388 if (curproxy != px &&
6389 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6390 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6391 "tracking: disable-on-404 option inconsistency.\n",
6392 proxy_type_str(curproxy), curproxy->id,
6393 newsrv->id, px->id, srv->id);
6394 cfgerr++;
6395 goto next_srv;
6396 }
6397
6398 /* if the other server is forced disabled, we have to do the same here */
6399 if (srv->state & SRV_MAINTAIN) {
6400 newsrv->state |= SRV_MAINTAIN;
6401 newsrv->state &= ~SRV_RUNNING;
6402 newsrv->health = 0;
6403 }
6404
6405 newsrv->track = srv;
6406 newsrv->tracknext = srv->tracknext;
6407 srv->tracknext = newsrv;
6408
6409 free(newsrv->trackit);
6410 newsrv->trackit = NULL;
6411 }
6412 next_srv:
6413 newsrv = newsrv->next;
6414 }
6415
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006416 /* We have to initialize the server lookup mechanism depending
6417 * on what LB algorithm was choosen.
6418 */
6419
6420 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6421 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6422 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006423 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6424 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6425 init_server_map(curproxy);
6426 } else {
6427 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6428 fwrr_init_server_groups(curproxy);
6429 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006430 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006431
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006432 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006433 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6434 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6435 fwlc_init_server_tree(curproxy);
6436 } else {
6437 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6438 fas_init_server_tree(curproxy);
6439 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006440 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006441
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006442 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006443 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6444 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6445 chash_init_server_tree(curproxy);
6446 } else {
6447 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6448 init_server_map(curproxy);
6449 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006450 break;
6451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452
6453 if (curproxy->options & PR_O_LOGASAP)
6454 curproxy->to_log &= ~LW_BYTES;
6455
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006456 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006457 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006458 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6459 proxy_type_str(curproxy), curproxy->id);
6460 err_code |= ERR_WARN;
6461 }
6462
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006463 if (curproxy->mode != PR_MODE_HTTP) {
6464 int optnum;
6465
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006466 if (curproxy->uri_auth) {
6467 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6468 proxy_type_str(curproxy), curproxy->id);
6469 err_code |= ERR_WARN;
6470 curproxy->uri_auth = NULL;
6471 }
6472
Willy Tarreau87cf5142011-08-19 22:57:24 +02006473 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006474 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6475 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6476 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006477 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006478 }
6479
6480 if (curproxy->options & PR_O_ORGTO) {
6481 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6482 "originalto", proxy_type_str(curproxy), curproxy->id);
6483 err_code |= ERR_WARN;
6484 curproxy->options &= ~PR_O_ORGTO;
6485 }
6486
6487 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6488 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6489 (curproxy->cap & cfg_opts[optnum].cap) &&
6490 (curproxy->options & cfg_opts[optnum].val)) {
6491 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6492 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6493 err_code |= ERR_WARN;
6494 curproxy->options &= ~cfg_opts[optnum].val;
6495 }
6496 }
6497
6498 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6499 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6500 (curproxy->cap & cfg_opts2[optnum].cap) &&
6501 (curproxy->options2 & cfg_opts2[optnum].val)) {
6502 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6503 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6504 err_code |= ERR_WARN;
6505 curproxy->options2 &= ~cfg_opts2[optnum].val;
6506 }
6507 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006508
Willy Tarreauefa5f512010-03-30 20:13:29 +02006509#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006510 if (curproxy->bind_hdr_occ) {
6511 curproxy->bind_hdr_occ = 0;
6512 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6513 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6514 err_code |= ERR_WARN;
6515 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006516#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006517 }
6518
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006520 * ensure that we're not cross-dressing a TCP server into HTTP.
6521 */
6522 newsrv = curproxy->srv;
6523 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006524 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006525 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6526 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006527 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006528 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006529
Willy Tarreau0cec3312011-10-31 13:49:26 +01006530 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6531 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6532 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6533 err_code |= ERR_WARN;
6534 }
6535
Willy Tarreauefa5f512010-03-30 20:13:29 +02006536#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006537 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6538 newsrv->bind_hdr_occ = 0;
6539 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6540 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6541 err_code |= ERR_WARN;
6542 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006543#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006544 newsrv = newsrv->next;
6545 }
6546
Willy Tarreauc1a21672009-08-16 22:37:44 +02006547 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006548 curproxy->accept = frontend_accept;
6549
Willy Tarreauc1a21672009-08-16 22:37:44 +02006550 if (curproxy->tcp_req.inspect_delay ||
6551 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006552 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006553
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006554 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006555 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006556 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006557 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006558
6559 /* both TCP and HTTP must check switching rules */
6560 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6561 }
6562
6563 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006564 if (curproxy->tcp_req.inspect_delay ||
6565 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6566 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6567
Emeric Brun97679e72010-09-23 17:56:44 +02006568 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6569 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6570
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006571 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006572 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006573 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006574 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006575
6576 /* If the backend does requires RDP cookie persistence, we have to
6577 * enable the corresponding analyser.
6578 */
6579 if (curproxy->options2 & PR_O2_RDPC_PRST)
6580 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6581 }
6582
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006583 listener = NULL;
6584 while (curproxy->listen) {
6585 struct listener *next;
6586
6587 next = curproxy->listen->next;
6588 curproxy->listen->next = listener;
6589 listener = curproxy->listen;
6590
6591 if (!next)
6592 break;
6593
6594 curproxy->listen = next;
6595 }
6596
Willy Tarreaue6b98942007-10-29 01:09:36 +01006597 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006598 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006599 listener = curproxy->listen;
6600 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006601 if (!listener->luid) {
6602 /* listener ID not set, use automatic numbering with first
6603 * spare entry starting with next_luid.
6604 */
6605 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6606 listener->conf.id.key = listener->luid = next_id;
6607 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006608 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006609 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006610
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006611 /* enable separate counters */
6612 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6613 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6614 if (!listener->name) {
6615 sprintf(trash, "sock-%d", listener->luid);
6616 listener->name = strdup(trash);
6617 }
6618 }
6619
Emeric Brun6e159292012-05-18 16:32:13 +02006620#ifdef USE_OPENSSL
6621#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6622#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6623#endif
6624#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6625#define SSL_OP_NO_COMPRESSION 0
6626#endif
6627#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6628#define SSL_MODE_RELEASE_BUFFERS 0
6629#endif
6630 /* Initialize SSL */
6631 if (listener->ssl_cert) {
6632 int ssloptions =
6633 SSL_OP_ALL | /* all known workarounds for bugs */
6634 SSL_OP_NO_SSLv2 |
6635 SSL_OP_NO_COMPRESSION |
6636 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6637 int sslmode =
6638 SSL_MODE_ENABLE_PARTIAL_WRITE |
6639 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6640 SSL_MODE_RELEASE_BUFFERS;
6641
6642 listener->data = &ssl_sock; /* data layer */
6643 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6644 if (!listener->ssl_ctx.ctx) {
6645 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6646 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6647 cfgerr++;
6648 goto skip_ssl;
6649 }
6650 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6651 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6652 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6653 SSL_CTX_set_session_cache_mode(listener->ssl_ctx.ctx, SSL_SESS_CACHE_SERVER);
6654
6655 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6656 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6657 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6658 cfgerr++;
6659 goto skip_ssl;
6660 }
6661
6662 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6663 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6664 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6665 cfgerr++;
6666 goto skip_ssl;
6667 }
6668 }
6669 skip_ssl:
6670#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006671 if (curproxy->options & PR_O_TCP_NOLING)
6672 listener->options |= LI_O_NOLINGER;
6673 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006674 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006675 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006676 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006677 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006678 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006679 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006680
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006681 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6682 listener->options |= LI_O_TCP_RULES;
6683
Willy Tarreaude3041d2010-05-31 10:56:17 +02006684 if (curproxy->mon_mask.s_addr)
6685 listener->options |= LI_O_CHK_MONNET;
6686
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006687 /* smart accept mode is automatic in HTTP mode */
6688 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6689 (curproxy->mode == PR_MODE_HTTP &&
6690 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6691 listener->options |= LI_O_NOQUICKACK;
6692
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006693 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006694 listener = listener->next;
6695 }
6696
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006697 /* Check multi-process mode compatibility for the current proxy */
6698 if (global.nbproc > 1) {
6699 int nbproc = 0;
6700 if (curproxy->bind_proc) {
6701 int proc;
6702 for (proc = 0; proc < global.nbproc; proc++) {
6703 if (curproxy->bind_proc & (1 << proc)) {
6704 nbproc++;
6705 }
6706 }
6707 } else {
6708 nbproc = global.nbproc;
6709 }
6710 if (curproxy->table.peers.name) {
6711 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6712 curproxy->id);
6713 cfgerr++;
6714 }
6715 if (nbproc > 1) {
6716 if (curproxy->uri_auth) {
6717 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6718 curproxy->id);
6719 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6720 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6721 curproxy->id);
6722 }
6723 }
6724 if (curproxy->appsession_name) {
6725 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6726 curproxy->id);
6727 }
6728 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6729 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6730 curproxy->id);
6731 }
6732 }
6733 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006734
6735 /* create the task associated with the proxy */
6736 curproxy->task = task_new();
6737 if (curproxy->task) {
6738 curproxy->task->context = curproxy;
6739 curproxy->task->process = manage_proxy;
6740 /* no need to queue, it will be done automatically if some
6741 * listener gets limited.
6742 */
6743 curproxy->task->expire = TICK_ETERNITY;
6744 } else {
6745 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6746 curproxy->id);
6747 cfgerr++;
6748 }
6749
Willy Tarreaubaaee002006-06-26 02:48:02 +02006750 curproxy = curproxy->next;
6751 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006752
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006753 /* Check multi-process mode compatibility */
6754 if (global.nbproc > 1) {
6755 if (global.stats_fe) {
6756 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6757 }
6758 }
6759
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006760 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6761 struct auth_users *curuser;
6762 int g;
6763
6764 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6765 unsigned int group_mask = 0;
6766 char *group = NULL;
6767
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006768 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006769 continue;
6770
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006771 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772
6773 for (g = 0; g < curuserlist->grpcnt; g++)
6774 if (!strcmp(curuserlist->groups[g], group))
6775 break;
6776
6777 if (g == curuserlist->grpcnt) {
6778 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6779 curuserlist->name, group, curuser->user);
6780 err_code |= ERR_ALERT | ERR_FATAL;
6781 goto out;
6782 }
6783
6784 group_mask |= (1 << g);
6785 }
6786
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006787 free(curuser->u.groups);
6788 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 }
6790
6791 for (g = 0; g < curuserlist->grpcnt; g++) {
6792 char *user = NULL;
6793
6794 if (!curuserlist->groupusers[g])
6795 continue;
6796
6797 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6798 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6799 if (!strcmp(curuser->user, user))
6800 break;
6801
6802 if (!curuser) {
6803 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6804 curuserlist->name, user, curuserlist->groups[g]);
6805 err_code |= ERR_ALERT | ERR_FATAL;
6806 goto out;
6807 }
6808
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006809 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006810 }
6811
6812 free(curuserlist->groupusers[g]);
6813 }
6814
6815 free(curuserlist->groupusers);
6816
6817#ifdef DEBUG_AUTH
6818 for (g = 0; g < curuserlist->grpcnt; g++) {
6819 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6820
6821 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006822 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006823 fprintf(stderr, " %s", curuser->user);
6824 }
6825
6826 fprintf(stderr, "\n");
6827 }
6828#endif
6829
Willy Tarreaufbb78422011-06-05 15:38:35 +02006830 }
6831
6832 /* automatically compute fullconn if not set. We must not do it in the
6833 * loop above because cross-references are not yet fully resolved.
6834 */
6835 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6836 /* If <fullconn> is not set, let's set it to 10% of the sum of
6837 * the possible incoming frontend's maxconns.
6838 */
6839 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6840 struct proxy *fe;
6841 int total = 0;
6842
6843 /* sum up the number of maxconns of frontends which
6844 * reference this backend at least once or which are
6845 * the same one ('listen').
6846 */
6847 for (fe = proxy; fe; fe = fe->next) {
6848 struct switching_rule *rule;
6849 struct hdr_exp *exp;
6850 int found = 0;
6851
6852 if (!(fe->cap & PR_CAP_FE))
6853 continue;
6854
6855 if (fe == curproxy) /* we're on a "listen" instance */
6856 found = 1;
6857
6858 if (fe->defbe.be == curproxy) /* "default_backend" */
6859 found = 1;
6860
6861 /* check if a "use_backend" rule matches */
6862 if (!found) {
6863 list_for_each_entry(rule, &fe->switching_rules, list) {
6864 if (rule->be.backend == curproxy) {
6865 found = 1;
6866 break;
6867 }
6868 }
6869 }
6870
6871 /* check if a "reqsetbe" rule matches */
6872 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6873 if (exp->action == ACT_SETBE &&
6874 (struct proxy *)exp->replace == curproxy) {
6875 found = 1;
6876 break;
6877 }
6878 }
6879
6880 /* now we've checked all possible ways to reference a backend
6881 * from a frontend.
6882 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006883 if (!found)
6884 continue;
6885 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006886 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006887 /* we have the sum of the maxconns in <total>. We only
6888 * keep 10% of that sum to set the default fullconn, with
6889 * a hard minimum of 1 (to avoid a divide by zero).
6890 */
6891 curproxy->fullconn = (total + 9) / 10;
6892 if (!curproxy->fullconn)
6893 curproxy->fullconn = 1;
6894 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006895 }
6896
Willy Tarreau056f5682010-06-06 15:51:11 +02006897 /* initialize stick-tables on backend capable proxies. This must not
6898 * be done earlier because the data size may be discovered while parsing
6899 * other proxies.
6900 */
6901 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006902 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006903
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006904 /*
6905 * Recount currently required checks.
6906 */
6907
6908 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6909 int optnum;
6910
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006911 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6912 if (curproxy->options & cfg_opts[optnum].val)
6913 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006914
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006915 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6916 if (curproxy->options2 & cfg_opts2[optnum].val)
6917 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006918 }
6919
Willy Tarreau122541c2011-09-07 21:24:49 +02006920 if (peers) {
6921 struct peers *curpeers = peers, **last;
6922 struct peer *p, *pb;
6923
6924 /* Remove all peers sections which don't have a valid listener.
6925 * This can happen when a peers section is never referenced and
6926 * does not contain a local peer.
6927 */
6928 last = &peers;
6929 while (*last) {
6930 curpeers = *last;
6931 if (curpeers->peers_fe) {
6932 last = &curpeers->next;
6933 continue;
6934 }
6935
6936 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6937 curpeers->id, localpeer);
6938
6939 p = curpeers->remote;
6940 while (p) {
6941 pb = p->next;
6942 free(p->id);
6943 free(p);
6944 p = pb;
6945 }
6946
6947 /* Destroy and unlink this curpeers section.
6948 * Note: curpeers is backed up into *last.
6949 */
6950 free(curpeers->id);
6951 curpeers = curpeers->next;
6952 free(*last);
6953 *last = curpeers;
6954 }
6955 }
6956
Willy Tarreauac1932d2011-10-24 19:14:41 +02006957 if (!global.tune.max_http_hdr)
6958 global.tune.max_http_hdr = MAX_HTTP_HDR;
6959
Willy Tarreau34eb6712011-10-24 18:15:04 +02006960 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006961 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006962 MEM_F_SHARED);
6963
Willy Tarreaubb925012009-07-23 13:36:36 +02006964 if (cfgerr > 0)
6965 err_code |= ERR_ALERT | ERR_FATAL;
6966 out:
6967 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006968}
6969
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006970/*
6971 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6972 * parsing sessions.
6973 */
6974void cfg_register_keywords(struct cfg_kw_list *kwl)
6975{
6976 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6977}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006978
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006979/*
6980 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6981 */
6982void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6983{
6984 LIST_DEL(&kwl->list);
6985 LIST_INIT(&kwl->list);
6986}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006987
6988/*
6989 * Local variables:
6990 * c-indent-level: 8
6991 * c-basic-offset: 8
6992 * End:
6993 */