blob: 2afd5e746409c8a8eacb61d94d8198fee3c26e7d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
36#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020037#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010040#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020041#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020042#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020044#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020045#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020046#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010048#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020052#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020064#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Emeric Brunfc0421f2012-09-07 17:30:07 +020068#ifdef USE_OPENSSL
69#include <types/ssl_sock.h>
70#include <proto/ssl_sock.h>
71#include <proto/shctx.h>
72#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020073
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
206 struct sockaddr_storage ss;
207
208 str = next;
209 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100210 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211 *next++ = 0;
212 }
213
Emeric Bruned760922010-10-22 17:59:25 +0200214 if (*str == '/') {
215 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
216 /* so compute max path */
217 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
218 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 +0200219
Emeric Bruned760922010-10-22 17:59:25 +0200220 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200222 goto fail;
223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200226 ss.ss_family = AF_UNIX;
227 if (global.unix_bind.prefix) {
228 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
229 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231 else {
232 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
233 }
234 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 }
236 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 ss2 = str2sa_range(str, &port, &end);
240 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200241 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200246 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 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 Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
263
264 for (; port <= end; port++) {
265 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
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 {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100414/* Report it if a request ACL condition uses some response-only parameters. It
415 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
416 * Note that <cond> may be NULL and then will be ignored.
417 */
418static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
419{
420 struct acl *acl;
421
422 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
423 return 0;
424
425 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
426 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
427 file, line, acl ? acl->name : "(unknown)");
428 return ERR_WARN;
429}
430
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100431/* Report it if a request ACL condition uses some request-only volatile parameters.
432 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
433 * Note that <cond> may be NULL and then will be ignored.
434 */
435static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
436{
437 struct acl *acl;
438
439 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
440 return 0;
441
442 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
443 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
444 file, line, acl ? acl->name : "(unknown)");
445 return ERR_WARN;
446}
447
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
468 else if (!strcmp(args[0], "daemon")) {
469 global.mode |= MODE_DAEMON;
470 }
471 else if (!strcmp(args[0], "debug")) {
472 global.mode |= MODE_DEBUG;
473 }
474 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200477 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 }
480 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100486 else if (!strcmp(args[0], "nosplice")) {
487 global.tune.options &= ~GTUNE_USE_SPLICE;
488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489 else if (!strcmp(args[0], "quiet")) {
490 global.mode |= MODE_QUIET;
491 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200492 else if (!strcmp(args[0], "tune.maxpollevents")) {
493 if (global.tune.maxpollevents != 0) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200495 err_code |= ERR_ALERT;
496 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200502 }
503 global.tune.maxpollevents = atol(args[1]);
504 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100505 else if (!strcmp(args[0], "tune.maxaccept")) {
506 if (global.tune.maxaccept != 0) {
507 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200508 err_code |= ERR_ALERT;
509 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100510 }
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100515 }
516 global.tune.maxaccept = atol(args[1]);
517 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200518 else if (!strcmp(args[0], "tune.chksize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.chksize = atol(args[1]);
525 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200526#ifdef USE_OPENSSL
527 else if (!strcmp(args[0], "tune.sslcachesize")) {
528 if (*(args[1]) == 0) {
529 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT | ERR_FATAL;
531 goto out;
532 }
533 global.tune.sslcachesize = atol(args[1]);
534 }
535#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200536 else if (!strcmp(args[0], "tune.bufsize")) {
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.bufsize = atol(args[1]);
543 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
544 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200545 trashlen = global.tune.bufsize;
546 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 }
548 else if (!strcmp(args[0], "tune.maxrewrite")) {
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
553 }
554 global.tune.maxrewrite = atol(args[1]);
555 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
556 global.tune.maxrewrite = global.tune.bufsize / 2;
557 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100558 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
559 if (global.tune.client_rcvbuf != 0) {
560 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT;
562 goto out;
563 }
564 if (*(args[1]) == 0) {
565 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT | ERR_FATAL;
567 goto out;
568 }
569 global.tune.client_rcvbuf = atol(args[1]);
570 }
571 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
572 if (global.tune.server_rcvbuf != 0) {
573 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT;
575 goto out;
576 }
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.server_rcvbuf = atol(args[1]);
583 }
584 else if (!strcmp(args[0], "tune.sndbuf.client")) {
585 if (global.tune.client_sndbuf != 0) {
586 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT;
588 goto out;
589 }
590 if (*(args[1]) == 0) {
591 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT | ERR_FATAL;
593 goto out;
594 }
595 global.tune.client_sndbuf = atol(args[1]);
596 }
597 else if (!strcmp(args[0], "tune.sndbuf.server")) {
598 if (global.tune.server_sndbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
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.server_sndbuf = atol(args[1]);
609 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200610 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
617 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200618 else if (!strcmp(args[0], "tune.http.maxhdr")) {
619 if (*(args[1]) == 0) {
620 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
621 err_code |= ERR_ALERT | ERR_FATAL;
622 goto out;
623 }
624 global.tune.max_http_hdr = atol(args[1]);
625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 else if (!strcmp(args[0], "uid")) {
627 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200628 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 if (*(args[1]) == 0) {
633 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT | ERR_FATAL;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 global.uid = atol(args[1]);
638 }
639 else if (!strcmp(args[0], "gid")) {
640 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200642 err_code |= ERR_ALERT;
643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200644 }
645 if (*(args[1]) == 0) {
646 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 }
650 global.gid = atol(args[1]);
651 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200652 /* user/group name handling */
653 else if (!strcmp(args[0], "user")) {
654 struct passwd *ha_user;
655 if (global.uid != 0) {
656 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200657 err_code |= ERR_ALERT;
658 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200659 }
660 errno = 0;
661 ha_user = getpwnam(args[1]);
662 if (ha_user != NULL) {
663 global.uid = (int)ha_user->pw_uid;
664 }
665 else {
666 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 +0200667 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 }
670 else if (!strcmp(args[0], "group")) {
671 struct group *ha_group;
672 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200673 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200676 }
677 errno = 0;
678 ha_group = getgrnam(args[1]);
679 if (ha_group != NULL) {
680 global.gid = (int)ha_group->gr_gid;
681 }
682 else {
683 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 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200685 }
686 }
687 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 else if (!strcmp(args[0], "nbproc")) {
689 if (global.nbproc != 0) {
690 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 global.nbproc = atol(args[1]);
700 }
701 else if (!strcmp(args[0], "maxconn")) {
702 if (global.maxconn != 0) {
703 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200704 err_code |= ERR_ALERT;
705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 }
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 }
712 global.maxconn = atol(args[1]);
713#ifdef SYSTEM_MAXCONN
714 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
715 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);
716 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200717 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200718 }
719#endif /* SYSTEM_MAXCONN */
720 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200721 else if (!strcmp(args[0], "maxsslconn")) {
722#ifdef USE_OPENSSL
723 if (*(args[1]) == 0) {
724 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
725 err_code |= ERR_ALERT | ERR_FATAL;
726 goto out;
727 }
728 global.maxsslconn = atol(args[1]);
729#else
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735#endif
736 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200737 else if (!strcmp(args[0], "maxconnrate")) {
738 if (global.cps_lim != 0) {
739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT;
741 goto out;
742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748 global.cps_lim = atol(args[1]);
749 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100750 else if (!strcmp(args[0], "maxpipes")) {
751 if (global.maxpipes != 0) {
752 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100755 }
756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100760 }
761 global.maxpipes = atol(args[1]);
762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763 else if (!strcmp(args[0], "ulimit-n")) {
764 if (global.rlimit_nofile != 0) {
765 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774 global.rlimit_nofile = atol(args[1]);
775 }
776 else if (!strcmp(args[0], "chroot")) {
777 if (global.chroot != NULL) {
778 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 if (*(args[1]) == 0) {
783 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200786 }
787 global.chroot = strdup(args[1]);
788 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200789 else if (!strcmp(args[0], "description")) {
790 int i, len=0;
791 char *d;
792
793 if (!*args[1]) {
794 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
795 file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799
800 for(i=1; *args[i]; i++)
801 len += strlen(args[i])+1;
802
803 if (global.desc)
804 free(global.desc);
805
806 global.desc = d = (char *)calloc(1, len);
807
808 d += sprintf(d, "%s", args[1]);
809 for(i=2; *args[i]; i++)
810 d += sprintf(d, " %s", args[i]);
811 }
812 else if (!strcmp(args[0], "node")) {
813 int i;
814 char c;
815
816 for (i=0; args[1][i]; i++) {
817 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100818 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
819 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200820 break;
821 }
822
823 if (!i || args[1][i]) {
824 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
825 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
826 file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830
831 if (global.node)
832 free(global.node);
833
834 global.node = strdup(args[1]);
835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 else if (!strcmp(args[0], "pidfile")) {
837 if (global.pidfile != NULL) {
838 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200846 }
847 global.pidfile = strdup(args[1]);
848 }
Emeric Bruned760922010-10-22 17:59:25 +0200849 else if (!strcmp(args[0], "unix-bind")) {
850 int cur_arg = 1;
851 while (*(args[cur_arg])) {
852 if (!strcmp(args[cur_arg], "prefix")) {
853 if (global.unix_bind.prefix != NULL) {
854 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
855 err_code |= ERR_ALERT;
856 cur_arg += 2;
857 continue;
858 }
859
860 if (*(args[cur_arg+1]) == 0) {
861 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865 global.unix_bind.prefix = strdup(args[cur_arg+1]);
866 cur_arg += 2;
867 continue;
868 }
869
870 if (!strcmp(args[cur_arg], "mode")) {
871
872 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
873 cur_arg += 2;
874 continue;
875 }
876
877 if (!strcmp(args[cur_arg], "uid")) {
878
879 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
880 cur_arg += 2;
881 continue;
882 }
883
884 if (!strcmp(args[cur_arg], "gid")) {
885
886 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
887 cur_arg += 2;
888 continue;
889 }
890
891 if (!strcmp(args[cur_arg], "user")) {
892 struct passwd *user;
893
894 user = getpwnam(args[cur_arg + 1]);
895 if (!user) {
896 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
897 file, linenum, args[0], args[cur_arg + 1 ]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901
902 global.unix_bind.ux.uid = user->pw_uid;
903 cur_arg += 2;
904 continue;
905 }
906
907 if (!strcmp(args[cur_arg], "group")) {
908 struct group *group;
909
910 group = getgrnam(args[cur_arg + 1]);
911 if (!group) {
912 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
913 file, linenum, args[0], args[cur_arg + 1 ]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917
918 global.unix_bind.ux.gid = group->gr_gid;
919 cur_arg += 2;
920 continue;
921 }
922
Willy Tarreaub48f9582011-09-05 01:17:06 +0200923 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200924 file, linenum, args[0]);
925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
927 }
928 }
William Lallemand0f99e342011-10-12 17:50:54 +0200929 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
930 /* delete previous herited or defined syslog servers */
931 struct logsrv *back;
932 struct logsrv *tmp;
933
934 if (*(args[1]) != 0) {
935 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939
940 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
941 LIST_DEL(&tmp->list);
942 free(tmp);
943 }
944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200946 struct logsrv *logsrv;
947
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 if (*(args[1]) == 0 || *(args[2]) == 0) {
949 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
William Lallemand0f99e342011-10-12 17:50:54 +0200953
954 logsrv = calloc(1, sizeof(struct logsrv));
955
956 logsrv->facility = get_log_facility(args[2]);
957 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200959 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200960 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 }
962
William Lallemand0f99e342011-10-12 17:50:54 +0200963 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200965 logsrv->level = get_log_level(args[3]);
966 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200968 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200969 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 }
972
William Lallemand0f99e342011-10-12 17:50:54 +0200973 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200974 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200975 logsrv->minlvl = get_log_level(args[4]);
976 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200977 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200979 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200980 }
981 }
982
Robert Tsai81ae1952007-12-05 10:47:29 +0100983 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100984 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100985 if (!sk) {
986 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100987 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100988 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200989 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100990 goto out;
991 }
William Lallemand0f99e342011-10-12 17:50:54 +0200992 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100993 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100994 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100995 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100996 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
997 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200998 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100999 goto out;
1000 }
William Lallemand0f99e342011-10-12 17:50:54 +02001001 logsrv->addr = *sk;
1002 if (!get_host_port(&logsrv->addr))
1003 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005
William Lallemand0f99e342011-10-12 17:50:54 +02001006 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001007 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001008 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1009 char *name;
1010 int len;
1011
1012 if (global.log_send_hostname != NULL) {
1013 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1014 err_code |= ERR_ALERT;
1015 goto out;
1016 }
1017
1018 if (*(args[1]))
1019 name = args[1];
1020 else
1021 name = hostname;
1022
1023 len = strlen(name);
1024
1025 /* We'll add a space after the name to respect the log format */
1026 free(global.log_send_hostname);
1027 global.log_send_hostname = malloc(len + 2);
1028 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1029 }
Kevinm48936af2010-12-22 16:08:21 +00001030 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1031 if (*(args[1]) == 0) {
1032 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035 }
1036 free(global.log_tag);
1037 global.log_tag = strdup(args[1]);
1038 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001039 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1040 if (global.spread_checks != 0) {
1041 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_ALERT;
1043 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001044 }
1045 if (*(args[1]) == 0) {
1046 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001049 }
1050 global.spread_checks = atol(args[1]);
1051 if (global.spread_checks < 0 || global.spread_checks > 50) {
1052 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 }
1056 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001057 struct cfg_kw_list *kwl;
1058 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001059 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060
1061 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1062 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1063 if (kwl->kw[index].section != CFG_GLOBAL)
1064 continue;
1065 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1066 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001067 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001068 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001069 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001070 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001071 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001073 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001074 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001075 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001076 err_code |= ERR_WARN;
1077 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001078 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001080 }
1081 }
1082 }
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001087
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001089 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091}
1092
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001093void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001095 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 defproxy.mode = PR_MODE_TCP;
1097 defproxy.state = PR_STNEW;
1098 defproxy.maxconn = cfg_maxpconn;
1099 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001100
1101 defproxy.defsrv.inter = DEF_CHKINTR;
1102 defproxy.defsrv.fastinter = 0;
1103 defproxy.defsrv.downinter = 0;
1104 defproxy.defsrv.rise = DEF_RISETIME;
1105 defproxy.defsrv.fall = DEF_FALLTIME;
1106 defproxy.defsrv.check_port = 0;
1107 defproxy.defsrv.maxqueue = 0;
1108 defproxy.defsrv.minconn = 0;
1109 defproxy.defsrv.maxconn = 0;
1110 defproxy.defsrv.slowstart = 0;
1111 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1112 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1113 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114}
1115
Willy Tarreauade5ec42010-01-28 19:33:49 +01001116
1117static int create_cond_regex_rule(const char *file, int line,
1118 struct proxy *px, int dir, int action, int flags,
1119 const char *cmd, const char *reg, const char *repl,
1120 const char **cond_start)
1121{
1122 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001123 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001124 const char *err;
1125 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001126 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127
1128 if (px == &defproxy) {
1129 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 if (*reg == 0) {
1135 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1141 err_code |= ERR_WARN;
1142
Willy Tarreau5321c422010-01-28 20:35:13 +01001143 if (cond_start &&
1144 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001145 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1146 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1147 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto err;
1150 }
1151 }
1152 else if (cond_start && **cond_start) {
1153 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1154 file, line, cmd, *cond_start);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto err;
1157 }
1158
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001159 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001160 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001161 else
1162 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001163
Willy Tarreauade5ec42010-01-28 19:33:49 +01001164 preg = calloc(1, sizeof(regex_t));
1165 if (!preg) {
1166 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1167 err_code = ERR_ALERT | ERR_FATAL;
1168 goto err;
1169 }
1170
1171 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1172 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1173 err_code = ERR_ALERT | ERR_FATAL;
1174 goto err;
1175 }
1176
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001177 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001178 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001179 if (repl && err) {
1180 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1181 file, line, cmd, *err);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto err;
1184 }
1185
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001186 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001187 err_code |= ERR_WARN;
1188
Willy Tarreauf4068b62012-05-08 17:37:49 +02001189 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001190 return err_code;
1191 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001192 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001193 free(preg);
1194 return err_code;
1195}
1196
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001198 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001199 * Returns the error code, 0 if OK, or any combination of :
1200 * - ERR_ABORT: must abort ASAP
1201 * - ERR_FATAL: we can continue parsing but not start the service
1202 * - ERR_WARN: a warning has been emitted
1203 * - ERR_ALERT: an alert has been emitted
1204 * Only the two first ones can stop processing, the two others are just
1205 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001207int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1208{
1209 static struct peers *curpeers = NULL;
1210 struct peer *newpeer = NULL;
1211 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001212 struct bind_conf *bind_conf;
1213 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001214 int err_code = 0;
1215
1216 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1217
1218 err = invalid_char(args[1]);
1219 if (err) {
1220 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1221 file, linenum, *err, args[0], args[1]);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 }
1224
1225 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1226 /*
1227 * If there are two proxies with the same name only following
1228 * combinations are allowed:
1229 */
1230 if (strcmp(curpeers->id, args[1]) == 0) {
1231 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1232 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1233 err_code |= ERR_WARN;
1234 }
1235 }
1236
1237 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1239 err_code |= ERR_ALERT | ERR_ABORT;
1240 goto out;
1241 }
1242
1243 curpeers->next = peers;
1244 peers = curpeers;
1245 curpeers->conf.file = file;
1246 curpeers->conf.line = linenum;
1247 curpeers->last_change = now.tv_sec;
1248 curpeers->id = strdup(args[1]);
1249 }
1250 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1251 char *rport, *raddr;
1252 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001253 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001254 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (!*args[2]) {
1257 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1258 file, linenum, args[0]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 goto out;
1261 }
1262
1263 err = invalid_char(args[1]);
1264 if (err) {
1265 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1266 file, linenum, *err, args[1]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 /* the peers are linked backwards first */
1278 curpeers->count++;
1279 newpeer->next = curpeers->remote;
1280 curpeers->remote = newpeer;
1281 newpeer->peers = curpeers;
1282 newpeer->conf.file = file;
1283 newpeer->conf.line = linenum;
1284
1285 newpeer->last_change = now.tv_sec;
1286 newpeer->id = strdup(args[1]);
1287
1288 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001289 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 if (rport) {
1291 *rport++ = 0;
1292 realport = atol(rport);
1293 }
1294 if (!realport) {
1295 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
Willy Tarreaufab5a432011-03-04 15:31:53 +01001300 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 free(raddr);
1302 if (!sk) {
1303 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001308 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001309 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001310 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001311
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001312 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001313 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1314 file, linenum, newpeer->addr.ss_family, args[2]);
1315 err_code |= ERR_ALERT | ERR_FATAL;
1316 goto out;
1317 }
1318
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001319 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320
1321 if (strcmp(newpeer->id, localpeer) == 0) {
1322 /* Current is local peer, it define a frontend */
1323 newpeer->local = 1;
1324
1325 if (!curpeers->peers_fe) {
1326 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1327 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1328 err_code |= ERR_ALERT | ERR_ABORT;
1329 goto out;
1330 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001331
Willy Tarreau237250c2011-07-29 01:49:03 +02001332 init_new_proxy(curpeers->peers_fe);
1333 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001334
1335 curpeers->peers_fe->last_change = now.tv_sec;
1336 curpeers->peers_fe->id = strdup(args[1]);
1337 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001338 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001339 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1340 curpeers->peers_fe->timeout.connect = 5000;
1341 curpeers->peers_fe->accept = peer_accept;
1342 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001343
1344 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1345
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001346 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1347 if (err_msg && *err_msg) {
1348 indent_msg(&err_msg, 2);
1349 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1350 }
1351 else
1352 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1353 file, linenum, args[0], args[1], args[2]);
1354 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001355 err_code |= ERR_FATAL;
1356 goto out;
1357 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001358
1359 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1360 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1361 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1362 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1363 l->accept = session_accept;
1364 l->handler = process_session;
1365 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1366 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1367 global.maxsock += l->maxconn;
1368 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001369 }
1370 }
1371 } /* neither "peer" nor "peers" */
1372 else if (*args[0] != 0) {
1373 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376 }
1377
1378out:
1379 return err_code;
1380}
1381
1382
Willy Tarreau3842f002009-06-14 11:39:52 +02001383int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384{
1385 static struct proxy *curproxy = NULL;
1386 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001387 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001388 int rc;
1389 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001390 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001391 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001392 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001393 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001394 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
Willy Tarreau977b8e42006-12-29 14:19:17 +01001396 if (!strcmp(args[0], "listen"))
1397 rc = PR_CAP_LISTEN;
1398 else if (!strcmp(args[0], "frontend"))
1399 rc = PR_CAP_FE | PR_CAP_RS;
1400 else if (!strcmp(args[0], "backend"))
1401 rc = PR_CAP_BE | PR_CAP_RS;
1402 else if (!strcmp(args[0], "ruleset"))
1403 rc = PR_CAP_RS;
1404 else
1405 rc = PR_CAP_NONE;
1406
1407 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 if (!*args[1]) {
1409 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1410 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1411 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001412 err_code |= ERR_ALERT | ERR_ABORT;
1413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001415
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001416 err = invalid_char(args[1]);
1417 if (err) {
1418 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1419 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001420 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001421 }
1422
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001423 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1424 /*
1425 * If there are two proxies with the same name only following
1426 * combinations are allowed:
1427 *
1428 * listen backend frontend ruleset
1429 * listen - - - -
1430 * backend - - OK -
1431 * frontend - OK - -
1432 * ruleset - - - -
1433 */
1434
1435 if (!strcmp(curproxy->id, args[1]) &&
1436 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1437 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001438 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1439 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1440 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001441 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001442 }
1443 }
1444
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1446 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001447 err_code |= ERR_ALERT | ERR_ABORT;
1448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001450
Willy Tarreau97cb7802010-01-03 20:23:58 +01001451 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 curproxy->next = proxy;
1453 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001454 curproxy->conf.file = file;
1455 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001456 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001458 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459
1460 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001462 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001463 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001464
Willy Tarreau4348fad2012-09-20 16:48:07 +02001465 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1466
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001467 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1468 if (err_msg && *err_msg) {
1469 indent_msg(&err_msg, 2);
1470 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1471 }
1472 else
1473 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1474 file, linenum, args[0], args[1], args[2]);
1475 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001476 err_code |= ERR_FATAL;
1477 goto out;
1478 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001479
Willy Tarreau4348fad2012-09-20 16:48:07 +02001480 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001481 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 }
1484
1485 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001486 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001487 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001488
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001491 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001492 curproxy->no_options = defproxy.no_options;
1493 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001494 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001495 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001496 curproxy->except_net = defproxy.except_net;
1497 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001498 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001499 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001501 if (defproxy.fwdfor_hdr_len) {
1502 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1503 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1504 }
1505
Willy Tarreaub86db342009-11-30 11:50:16 +01001506 if (defproxy.orgto_hdr_len) {
1507 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1508 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1509 }
1510
Mark Lamourinec2247f02012-01-04 13:02:01 -05001511 if (defproxy.server_id_hdr_len) {
1512 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1513 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1514 }
1515
Willy Tarreau977b8e42006-12-29 14:19:17 +01001516 if (curproxy->cap & PR_CAP_FE) {
1517 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001518 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001519 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520
1521 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001522 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1523 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524
1525 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527
Willy Tarreau977b8e42006-12-29 14:19:17 +01001528 if (curproxy->cap & PR_CAP_BE) {
1529 curproxy->fullconn = defproxy.fullconn;
1530 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001532 if (defproxy.check_req) {
1533 curproxy->check_req = calloc(1, defproxy.check_len);
1534 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1535 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001538 if (defproxy.expect_str) {
1539 curproxy->expect_str = strdup(defproxy.expect_str);
1540 if (defproxy.expect_regex) {
1541 /* note: this regex is known to be valid */
1542 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1543 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1544 }
1545 }
1546
Willy Tarreau67402132012-05-31 20:40:20 +02001547 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001548 if (defproxy.cookie_name)
1549 curproxy->cookie_name = strdup(defproxy.cookie_name);
1550 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001551 if (defproxy.cookie_domain)
1552 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001553
Willy Tarreau31936852010-10-06 16:59:56 +02001554 if (defproxy.cookie_maxidle)
1555 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1556
1557 if (defproxy.cookie_maxlife)
1558 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1559
Emeric Brun647caf12009-06-30 17:57:00 +02001560 if (defproxy.rdp_cookie_name)
1561 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1562 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1563
Willy Tarreau01732802007-11-01 22:48:15 +01001564 if (defproxy.url_param_name)
1565 curproxy->url_param_name = strdup(defproxy.url_param_name);
1566 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001567
Benoitaffb4812009-03-25 13:02:10 +01001568 if (defproxy.hh_name)
1569 curproxy->hh_name = strdup(defproxy.hh_name);
1570 curproxy->hh_len = defproxy.hh_len;
1571 curproxy->hh_match_domain = defproxy.hh_match_domain;
1572
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001573 if (defproxy.iface_name)
1574 curproxy->iface_name = strdup(defproxy.iface_name);
1575 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001576 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001578 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 if (defproxy.capture_name)
1580 curproxy->capture_name = strdup(defproxy.capture_name);
1581 curproxy->capture_namelen = defproxy.capture_namelen;
1582 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001586 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001587 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001588 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001589 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 curproxy->uri_auth = defproxy.uri_auth;
1591 curproxy->mon_net = defproxy.mon_net;
1592 curproxy->mon_mask = defproxy.mon_mask;
1593 if (defproxy.monitor_uri)
1594 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1595 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001596 if (defproxy.defbe.name)
1597 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001598
1599 /* get either a pointer to the logformat string or a copy of it */
1600 curproxy->logformat_string = defproxy.logformat_string;
1601 if (curproxy->logformat_string &&
1602 curproxy->logformat_string != default_http_log_format &&
1603 curproxy->logformat_string != default_tcp_log_format &&
1604 curproxy->logformat_string != clf_http_log_format)
1605 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001606 }
1607
1608 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001609 curproxy->timeout.connect = defproxy.timeout.connect;
1610 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001611 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001612 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001613 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001614 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001615 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001616 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 curproxy->source_addr = defproxy.source_addr;
1618 }
1619
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001621
1622 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001623 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001624 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001625 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001626 LIST_INIT(&node->list);
1627 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1628 }
1629
Willy Tarreau196729e2012-05-31 19:30:26 +02001630 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1631 if (curproxy->uniqueid_format_string)
1632 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001633
1634 /* copy default header unique id */
1635 if (defproxy.header_unique_id)
1636 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1637
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001639 curproxy->conf.used_listener_id = EB_ROOT;
1640 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001641
Willy Tarreau93893792009-07-23 13:19:11 +02001642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 }
1644 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1645 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001646 /* FIXME-20070101: we should do this too at the end of the
1647 * config parsing to free all default values.
1648 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001649 free(defproxy.check_req);
1650 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001651 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001652 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001653 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001654 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001655 free(defproxy.capture_name);
1656 free(defproxy.monitor_uri);
1657 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001658 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001659 free(defproxy.fwdfor_hdr_name);
1660 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001661 free(defproxy.orgto_hdr_name);
1662 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001663 free(defproxy.server_id_hdr_name);
1664 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001665 free(defproxy.expect_str);
1666 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001667
Willy Tarreau39b06652012-06-01 10:58:06 +02001668 if (defproxy.logformat_string != default_http_log_format &&
1669 defproxy.logformat_string != default_tcp_log_format &&
1670 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001671 free(defproxy.logformat_string);
1672
1673 free(defproxy.uniqueid_format_string);
1674
Willy Tarreaua534fea2008-08-03 12:19:50 +02001675 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001676 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001677
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 /* we cannot free uri_auth because it might already be used */
1679 init_default_instance();
1680 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001681 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 }
1684 else if (curproxy == NULL) {
1685 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
1689
Willy Tarreau977b8e42006-12-29 14:19:17 +01001690
1691 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001693 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001694 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001695 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001696
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 if (curproxy == &defproxy) {
1698 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001703 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704
Emeric Bruned760922010-10-22 17:59:25 +02001705 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001706 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001711
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001712 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001713 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001714
1715 /* NOTE: the following line might create several listeners if there
1716 * are comma-separated IPs or port ranges. So all further processing
1717 * will have to be applied to all listeners created after last_listen.
1718 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001719 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1720 if (err_msg && *err_msg) {
1721 indent_msg(&err_msg, 2);
1722 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1723 }
1724 else
1725 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1726 file, linenum, args[0], args[1]);
1727 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001731
Willy Tarreau4348fad2012-09-20 16:48:07 +02001732 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1733 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001734 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001735 }
1736
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001737 cur_arg = 2;
1738 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001739 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001740 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001741 char *err;
1742
Willy Tarreau26982662012-09-12 23:17:10 +02001743 kw = bind_find_kw(args[cur_arg]);
1744 if (kw) {
1745 char *err = NULL;
1746 int code;
1747
1748 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001749 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1750 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001751 cur_arg += 1 + kw->skip ;
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
Willy Tarreau4348fad2012-09-20 16:48:07 +02001756 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001757 err_code |= code;
1758
1759 if (code) {
1760 if (err && *err) {
1761 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001762 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001763 }
1764 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001765 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1766 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001767 if (code & ERR_FATAL) {
1768 free(err);
1769 cur_arg += 1 + kw->skip;
1770 goto out;
1771 }
1772 }
1773 free(err);
1774 cur_arg += 1 + kw->skip;
1775 continue;
1776 }
1777
Willy Tarreau8638f482012-09-18 18:01:17 +02001778 err = NULL;
1779 if (!bind_dumped) {
1780 bind_dump_kws(&err);
1781 indent_msg(&err, 4);
1782 bind_dumped = 1;
1783 }
1784
1785 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1786 file, linenum, args[0], args[1], args[cur_arg],
1787 err ? " Registered keywords :" : "", err ? err : "");
1788 free(err);
1789
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001792 }
Willy Tarreau93893792009-07-23 13:19:11 +02001793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 }
1795 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1796 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1797 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 /* flush useless bits */
1806 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001809 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001812
Willy Tarreau1c47f852006-07-09 08:22:27 +02001813 if (!*args[1]) {
1814 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1815 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001818 }
1819
Willy Tarreaua534fea2008-08-03 12:19:50 +02001820 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001821 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001822 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001823 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001824 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1825
Willy Tarreau93893792009-07-23 13:19:11 +02001826 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1829 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1830 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1831 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1832 else {
1833 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 }
1837 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001838 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001839 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001840
1841 if (curproxy == &defproxy) {
1842 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1843 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001846 }
1847
1848 if (!*args[1]) {
1849 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001853 }
1854
1855 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001856 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001857
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001858 if (curproxy->uuid <= 0) {
1859 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001860 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001861 err_code |= ERR_ALERT | ERR_FATAL;
1862 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001863 }
1864
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001865 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1866 if (node) {
1867 struct proxy *target = container_of(node, struct proxy, conf.id);
1868 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1869 file, linenum, proxy_type_str(curproxy), curproxy->id,
1870 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
1873 }
1874 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001875 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001876 else if (!strcmp(args[0], "description")) {
1877 int i, len=0;
1878 char *d;
1879
Cyril Bonté99ed3272010-01-24 23:29:44 +01001880 if (curproxy == &defproxy) {
1881 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1882 file, linenum, args[0]);
1883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
1885 }
1886
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001887 if (!*args[1]) {
1888 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1889 file, linenum, args[0]);
1890 return -1;
1891 }
1892
1893 for(i=1; *args[i]; i++)
1894 len += strlen(args[i])+1;
1895
1896 d = (char *)calloc(1, len);
1897 curproxy->desc = d;
1898
1899 d += sprintf(d, "%s", args[1]);
1900 for(i=2; *args[i]; i++)
1901 d += sprintf(d, " %s", args[i]);
1902
1903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1905 curproxy->state = PR_STSTOPPED;
1906 }
1907 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1908 curproxy->state = PR_STNEW;
1909 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001910 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1911 int cur_arg = 1;
1912 unsigned int set = 0;
1913
1914 while (*args[cur_arg]) {
1915 int u;
1916 if (strcmp(args[cur_arg], "all") == 0) {
1917 set = 0;
1918 break;
1919 }
1920 else if (strcmp(args[cur_arg], "odd") == 0) {
1921 set |= 0x55555555;
1922 }
1923 else if (strcmp(args[cur_arg], "even") == 0) {
1924 set |= 0xAAAAAAAA;
1925 }
1926 else {
1927 u = str2uic(args[cur_arg]);
1928 if (u < 1 || u > 32) {
1929 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001933 }
1934 if (u > global.nbproc) {
1935 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001938 }
1939 set |= 1 << (u - 1);
1940 }
1941 cur_arg++;
1942 }
1943 curproxy->bind_proc = set;
1944 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001945 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001946 if (curproxy == &defproxy) {
1947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001950 }
1951
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001952 err = invalid_char(args[1]);
1953 if (err) {
1954 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1955 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001957 }
1958
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001959 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
1960 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
1961 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001964 }
1965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1967 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001971
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 if (*(args[1]) == 0) {
1973 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001978
Willy Tarreau67402132012-05-31 20:40:20 +02001979 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001980 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001981 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001982 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->cookie_name = strdup(args[1]);
1984 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02001985
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986 cur_arg = 2;
1987 while (*(args[cur_arg])) {
1988 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001989 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 }
1991 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001992 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 }
1994 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001995 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001996 }
1997 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02001998 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 }
2000 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002001 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002003 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002004 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002007 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002009 else if (!strcmp(args[cur_arg], "httponly")) {
2010 curproxy->ck_opts |= PR_CK_HTTPONLY;
2011 }
2012 else if (!strcmp(args[cur_arg], "secure")) {
2013 curproxy->ck_opts |= PR_CK_SECURE;
2014 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002015 else if (!strcmp(args[cur_arg], "domain")) {
2016 if (!*args[cur_arg + 1]) {
2017 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2018 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002021 }
2022
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002023 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002024 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002025 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2026 " dots nor does not start with a dot."
2027 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002028 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002029 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002030 }
2031
2032 err = invalid_domainchar(args[cur_arg + 1]);
2033 if (err) {
2034 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2035 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002038 }
2039
Willy Tarreau68a897b2009-12-03 23:28:34 +01002040 if (!curproxy->cookie_domain) {
2041 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2042 } else {
2043 /* one domain was already specified, add another one by
2044 * building the string which will be returned along with
2045 * the cookie.
2046 */
2047 char *new_ptr;
2048 int new_len = strlen(curproxy->cookie_domain) +
2049 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2050 new_ptr = malloc(new_len);
2051 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2052 free(curproxy->cookie_domain);
2053 curproxy->cookie_domain = new_ptr;
2054 }
Willy Tarreau31936852010-10-06 16:59:56 +02002055 cur_arg++;
2056 }
2057 else if (!strcmp(args[cur_arg], "maxidle")) {
2058 unsigned int maxidle;
2059 const char *res;
2060
2061 if (!*args[cur_arg + 1]) {
2062 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2063 file, linenum, args[cur_arg]);
2064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
2066 }
2067
2068 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2069 if (res) {
2070 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2071 file, linenum, *res, args[cur_arg]);
2072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
2074 }
2075 curproxy->cookie_maxidle = maxidle;
2076 cur_arg++;
2077 }
2078 else if (!strcmp(args[cur_arg], "maxlife")) {
2079 unsigned int maxlife;
2080 const char *res;
2081
2082 if (!*args[cur_arg + 1]) {
2083 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2084 file, linenum, args[cur_arg]);
2085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
2087 }
2088
2089 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2090 if (res) {
2091 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2092 file, linenum, *res, args[cur_arg]);
2093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
2095 }
2096 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 cur_arg++;
2098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002100 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 +02002101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002102 err_code |= ERR_ALERT | ERR_FATAL;
2103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
2105 cur_arg++;
2106 }
Willy Tarreau67402132012-05-31 20:40:20 +02002107 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2109 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 }
2112
Willy Tarreau67402132012-05-31 20:40:20 +02002113 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2115 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002116 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002118
Willy Tarreau67402132012-05-31 20:40:20 +02002119 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002120 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2121 file, linenum);
2122 err_code |= ERR_ALERT | ERR_FATAL;
2123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002125 else if (!strcmp(args[0], "persist")) { /* persist */
2126 if (*(args[1]) == 0) {
2127 Alert("parsing [%s:%d] : missing persist method.\n",
2128 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002131 }
2132
2133 if (!strncmp(args[1], "rdp-cookie", 10)) {
2134 curproxy->options2 |= PR_O2_RDPC_PRST;
2135
Emeric Brunb982a3d2010-01-04 15:45:53 +01002136 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002137 const char *beg, *end;
2138
2139 beg = args[1] + 11;
2140 end = strchr(beg, ')');
2141
2142 if (!end || end == beg) {
2143 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2144 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002147 }
2148
2149 free(curproxy->rdp_cookie_name);
2150 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2151 curproxy->rdp_cookie_len = end-beg;
2152 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002153 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002154 free(curproxy->rdp_cookie_name);
2155 curproxy->rdp_cookie_name = strdup("msts");
2156 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2157 }
2158 else { /* syntax */
2159 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2160 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002163 }
2164 }
2165 else {
2166 Alert("parsing [%s:%d] : unknown persist method.\n",
2167 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002170 }
2171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002173 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002175 if (curproxy == &defproxy) {
2176 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
Willy Tarreau977b8e42006-12-29 14:19:17 +01002181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002183
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002185 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
2190 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002191 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 curproxy->appsession_name = strdup(args[1]);
2193 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2194 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002195 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2196 if (err) {
2197 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2198 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002201 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002202 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002203
Willy Tarreau51041c72007-09-09 21:56:53 +02002204 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2205 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002209
2210 cur_arg = 6;
2211 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002212 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2213 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002214 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002215 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002216 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002217 } else if (!strcmp(args[cur_arg], "prefix")) {
2218 curproxy->options2 |= PR_O2_AS_PFX;
2219 } else if (!strcmp(args[cur_arg], "mode")) {
2220 if (!*args[cur_arg + 1]) {
2221 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2222 file, linenum, args[0], args[cur_arg]);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226
2227 cur_arg++;
2228 if (!strcmp(args[cur_arg], "query-string")) {
2229 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2230 curproxy->options2 |= PR_O2_AS_M_QS;
2231 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2232 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2233 curproxy->options2 |= PR_O2_AS_M_PP;
2234 } else {
2235 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002240 cur_arg++;
2241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 } /* Url App Session */
2243 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002244 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002246
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 if (*(args[4]) == 0) {
2255 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2256 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002260 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 curproxy->capture_name = strdup(args[2]);
2262 curproxy->capture_namelen = strlen(curproxy->capture_name);
2263 curproxy->capture_len = atol(args[4]);
2264 if (curproxy->capture_len >= CAPTURE_LEN) {
2265 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2266 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 curproxy->capture_len = CAPTURE_LEN - 1;
2269 }
2270 curproxy->to_log |= LW_COOKIE;
2271 }
2272 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2273 struct cap_hdr *hdr;
2274
2275 if (curproxy == &defproxy) {
2276 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 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280
2281 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2282 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2283 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 }
2287
2288 hdr = calloc(sizeof(struct cap_hdr), 1);
2289 hdr->next = curproxy->req_cap;
2290 hdr->name = strdup(args[3]);
2291 hdr->namelen = strlen(args[3]);
2292 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002293 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 hdr->index = curproxy->nb_req_cap++;
2295 curproxy->req_cap = hdr;
2296 curproxy->to_log |= LW_REQHDR;
2297 }
2298 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2299 struct cap_hdr *hdr;
2300
2301 if (curproxy == &defproxy) {
2302 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 +02002303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306
2307 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2308 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2309 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002310 err_code |= ERR_ALERT | ERR_FATAL;
2311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 }
2313 hdr = calloc(sizeof(struct cap_hdr), 1);
2314 hdr->next = curproxy->rsp_cap;
2315 hdr->name = strdup(args[3]);
2316 hdr->namelen = strlen(args[3]);
2317 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002318 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 hdr->index = curproxy->nb_rsp_cap++;
2320 curproxy->rsp_cap = hdr;
2321 curproxy->to_log |= LW_RSPHDR;
2322 }
2323 else {
2324 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
2329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002332 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002333
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 if (*(args[1]) == 0) {
2335 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2336 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 }
2340 curproxy->conn_retries = atol(args[1]);
2341 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002342 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002343 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002344
2345 if (curproxy == &defproxy) {
2346 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350
Willy Tarreauff011f22011-01-06 17:51:27 +01002351 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 +01002352 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2353 file, linenum, args[0]);
2354 err_code |= ERR_WARN;
2355 }
2356
Willy Tarreauff011f22011-01-06 17:51:27 +01002357 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002358
Willy Tarreauff011f22011-01-06 17:51:27 +01002359 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
2362 }
2363
Willy Tarreauff011f22011-01-06 17:51:27 +01002364 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2365 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002366 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002367 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2368 /* set the header name and length into the proxy structure */
2369 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2370 err_code |= ERR_WARN;
2371
2372 if (!*args[1]) {
2373 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2374 file, linenum, args[0]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 /* set the desired header name */
2380 free(curproxy->server_id_hdr_name);
2381 curproxy->server_id_hdr_name = strdup(args[1]);
2382 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2383 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002384 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002385 if (curproxy == &defproxy) {
2386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002389 }
2390
Willy Tarreauef6494c2010-01-28 17:12:36 +01002391 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002392 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002396 }
2397
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002398 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2399 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2400 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002403 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002404
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002405 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002406 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002407 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002408 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002409 struct redirect_rule *rule;
2410 int cur_arg;
2411 int type = REDIRECT_TYPE_NONE;
2412 int code = 302;
2413 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002414 char *cookie = NULL;
2415 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002416 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002417
Cyril Bonté99ed3272010-01-24 23:29:44 +01002418 if (curproxy == &defproxy) {
2419 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002424 cur_arg = 1;
2425 while (*(args[cur_arg])) {
2426 if (!strcmp(args[cur_arg], "location")) {
2427 if (!*args[cur_arg + 1]) {
2428 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2429 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002432 }
2433
2434 type = REDIRECT_TYPE_LOCATION;
2435 cur_arg++;
2436 destination = args[cur_arg];
2437 }
2438 else if (!strcmp(args[cur_arg], "prefix")) {
2439 if (!*args[cur_arg + 1]) {
2440 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2441 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002444 }
2445
2446 type = REDIRECT_TYPE_PREFIX;
2447 cur_arg++;
2448 destination = args[cur_arg];
2449 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002450 else if (!strcmp(args[cur_arg], "scheme")) {
2451 if (!*args[cur_arg + 1]) {
2452 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2453 file, linenum, args[0], args[cur_arg]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 type = REDIRECT_TYPE_SCHEME;
2459 cur_arg++;
2460 destination = args[cur_arg];
2461 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002462 else if (!strcmp(args[cur_arg], "set-cookie")) {
2463 if (!*args[cur_arg + 1]) {
2464 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2465 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002468 }
2469
2470 cur_arg++;
2471 cookie = args[cur_arg];
2472 cookie_set = 1;
2473 }
2474 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2475 if (!*args[cur_arg + 1]) {
2476 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2477 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002480 }
2481
2482 cur_arg++;
2483 cookie = args[cur_arg];
2484 cookie_set = 0;
2485 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002486 else if (!strcmp(args[cur_arg],"code")) {
2487 if (!*args[cur_arg + 1]) {
2488 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002492 }
2493 cur_arg++;
2494 code = atol(args[cur_arg]);
2495 if (code < 301 || code > 303) {
2496 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2497 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002500 }
2501 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002502 else if (!strcmp(args[cur_arg],"drop-query")) {
2503 flags |= REDIRECT_FLAG_DROP_QS;
2504 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002505 else if (!strcmp(args[cur_arg],"append-slash")) {
2506 flags |= REDIRECT_FLAG_APPEND_SLASH;
2507 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002508 else if (strcmp(args[cur_arg], "if") == 0 ||
2509 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002510 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002511 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002512 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2513 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
2516 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002517 break;
2518 }
2519 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002520 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002521 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002524 }
2525 cur_arg++;
2526 }
2527
2528 if (type == REDIRECT_TYPE_NONE) {
2529 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 }
2534
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002535 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2536 rule->cond = cond;
2537 rule->rdr_str = strdup(destination);
2538 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002539 if (cookie) {
2540 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002541 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002542 */
2543 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002544 if (cookie_set) {
2545 rule->cookie_str = malloc(rule->cookie_len + 10);
2546 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2547 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2548 rule->cookie_len += 9;
2549 } else {
2550 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002551 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002552 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2553 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002554 }
2555 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002556 rule->type = type;
2557 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002558 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002559 LIST_INIT(&rule->list);
2560 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002561 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2562 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002564 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002565 struct switching_rule *rule;
2566
Willy Tarreaub099aca2008-10-12 17:26:37 +02002567 if (curproxy == &defproxy) {
2568 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002571 }
2572
Willy Tarreau55ea7572007-06-17 19:56:27 +02002573 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002575
2576 if (*(args[1]) == 0) {
2577 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002580 }
2581
Willy Tarreauef6494c2010-01-28 17:12:36 +01002582 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002583 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002587 }
2588
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002589 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2590 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2591 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002594 }
2595
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002596 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002597
Willy Tarreau55ea7572007-06-17 19:56:27 +02002598 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2599 rule->cond = cond;
2600 rule->be.name = strdup(args[1]);
2601 LIST_INIT(&rule->list);
2602 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2603 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002604 else if (strcmp(args[0], "use-server") == 0) {
2605 struct server_rule *rule;
2606
2607 if (curproxy == &defproxy) {
2608 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
2613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2614 err_code |= ERR_WARN;
2615
2616 if (*(args[1]) == 0) {
2617 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
2620 }
2621
2622 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2623 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2624 file, linenum, args[0]);
2625 err_code |= ERR_ALERT | ERR_FATAL;
2626 goto out;
2627 }
2628
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002629 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2630 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2631 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
2634 }
2635
2636 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2637
2638 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2639 rule->cond = cond;
2640 rule->srv.name = strdup(args[1]);
2641 LIST_INIT(&rule->list);
2642 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2643 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2644 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002645 else if ((!strcmp(args[0], "force-persist")) ||
2646 (!strcmp(args[0], "ignore-persist"))) {
2647 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002648
2649 if (curproxy == &defproxy) {
2650 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654
2655 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2656 err_code |= ERR_WARN;
2657
Willy Tarreauef6494c2010-01-28 17:12:36 +01002658 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002659 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2660 file, linenum, args[0]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002665 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2666 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2667 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002672 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002673
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002674 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002675 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002676 if (!strcmp(args[0], "force-persist")) {
2677 rule->type = PERSIST_TYPE_FORCE;
2678 } else {
2679 rule->type = PERSIST_TYPE_IGNORE;
2680 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002682 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002683 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002684 else if (!strcmp(args[0], "stick-table")) {
2685 int myidx = 1;
2686
Emeric Brun32da3c42010-09-23 18:39:19 +02002687 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002688 curproxy->table.type = (unsigned int)-1;
2689 while (*args[myidx]) {
2690 const char *err;
2691
2692 if (strcmp(args[myidx], "size") == 0) {
2693 myidx++;
2694 if (!*(args[myidx])) {
2695 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2696 file, linenum, args[myidx-1]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2701 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2702 file, linenum, *err, args[myidx-1]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002706 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002707 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002708 else if (strcmp(args[myidx], "peers") == 0) {
2709 myidx++;
2710 if (!*(args[myidx])) {
2711 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2712 file, linenum, args[myidx-1]);
2713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
2715 }
2716 curproxy->table.peers.name = strdup(args[myidx++]);
2717 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002718 else if (strcmp(args[myidx], "expire") == 0) {
2719 myidx++;
2720 if (!*(args[myidx])) {
2721 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2722 file, linenum, args[myidx-1]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2727 if (err) {
2728 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2729 file, linenum, *err, args[myidx-1]);
2730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
2732 }
2733 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002734 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002735 }
2736 else if (strcmp(args[myidx], "nopurge") == 0) {
2737 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002738 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002739 }
2740 else if (strcmp(args[myidx], "type") == 0) {
2741 myidx++;
2742 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2743 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2744 file, linenum, args[myidx]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002748 /* myidx already points to next arg */
2749 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002750 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002751 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002752 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002753
2754 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002755 nw = args[myidx];
2756 while (*nw) {
2757 /* the "store" keyword supports a comma-separated list */
2758 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002759 sa = NULL; /* store arg */
2760 while (*nw && *nw != ',') {
2761 if (*nw == '(') {
2762 *nw = 0;
2763 sa = ++nw;
2764 while (*nw != ')') {
2765 if (!*nw) {
2766 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2767 file, linenum, args[0], cw);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
2771 nw++;
2772 }
2773 *nw = '\0';
2774 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002775 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002776 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 if (*nw)
2778 *nw++ = '\0';
2779 type = stktable_get_data_type(cw);
2780 if (type < 0) {
2781 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2782 file, linenum, args[0], cw);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
Willy Tarreauac782882010-06-20 10:41:54 +02002786
2787 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2788 switch (err) {
2789 case PE_NONE: break;
2790 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002791 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2792 file, linenum, args[0], cw);
2793 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002794 break;
2795
2796 case PE_ARG_MISSING:
2797 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2798 file, linenum, args[0], cw);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801
2802 case PE_ARG_NOT_USED:
2803 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807
2808 default:
2809 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2810 file, linenum, args[0], cw);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002814 }
2815 myidx++;
2816 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002817 else {
2818 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2819 file, linenum, args[myidx]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002822 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 }
2824
2825 if (!curproxy->table.size) {
2826 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2827 file, linenum);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831
2832 if (curproxy->table.type == (unsigned int)-1) {
2833 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2834 file, linenum);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
2837 }
2838 }
2839 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002841 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002842 int myidx = 0;
2843 const char *name = NULL;
2844 int flags;
2845
2846 if (curproxy == &defproxy) {
2847 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
2852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2853 err_code |= ERR_WARN;
2854 goto out;
2855 }
2856
2857 myidx++;
2858 if ((strcmp(args[myidx], "store") == 0) ||
2859 (strcmp(args[myidx], "store-request") == 0)) {
2860 myidx++;
2861 flags = STK_IS_STORE;
2862 }
2863 else if (strcmp(args[myidx], "store-response") == 0) {
2864 myidx++;
2865 flags = STK_IS_STORE | STK_ON_RSP;
2866 }
2867 else if (strcmp(args[myidx], "match") == 0) {
2868 myidx++;
2869 flags = STK_IS_MATCH;
2870 }
2871 else if (strcmp(args[myidx], "on") == 0) {
2872 myidx++;
2873 flags = STK_IS_MATCH | STK_IS_STORE;
2874 }
2875 else {
2876 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2877 err_code |= ERR_ALERT | ERR_FATAL;
2878 goto out;
2879 }
2880
2881 if (*(args[myidx]) == 0) {
2882 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
David du Colombier7af46052012-05-16 14:16:48 +02002887 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002888 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002889 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002895 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002896 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2897 file, linenum, args[0], expr->fetch->kw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002899 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002900 goto out;
2901 }
2902 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002903 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002904 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2905 file, linenum, args[0], expr->fetch->kw);
2906 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002907 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 goto out;
2909 }
2910 }
2911
2912 if (strcmp(args[myidx], "table") == 0) {
2913 myidx++;
2914 name = args[myidx++];
2915 }
2916
Willy Tarreauef6494c2010-01-28 17:12:36 +01002917 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002918 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2919 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2920 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002921 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002922 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 goto out;
2924 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002926 else if (*(args[myidx])) {
2927 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2928 file, linenum, args[0], args[myidx]);
2929 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002930 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002931 goto out;
2932 }
Emeric Brun97679e72010-09-23 17:56:44 +02002933 if (flags & STK_ON_RSP)
2934 err_code |= warnif_cond_requires_req(cond, file, linenum);
2935 else
2936 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002937
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2939 rule->cond = cond;
2940 rule->expr = expr;
2941 rule->flags = flags;
2942 rule->table.name = name ? strdup(name) : NULL;
2943 LIST_INIT(&rule->list);
2944 if (flags & STK_ON_RSP)
2945 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2946 else
2947 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2954 curproxy->uri_auth = NULL; /* we must detach from the default config */
2955
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002956 if (!*args[1]) {
2957 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002958 } else if (!strcmp(args[1], "admin")) {
2959 struct stats_admin_rule *rule;
2960
2961 if (curproxy == &defproxy) {
2962 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
2965 }
2966
2967 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2968 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2969 err_code |= ERR_ALERT | ERR_ABORT;
2970 goto out;
2971 }
2972
2973 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2974 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2975 file, linenum, args[0], args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002979 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2980 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
2981 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
2986 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2987
2988 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2989 rule->cond = cond;
2990 LIST_INIT(&rule->list);
2991 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002992 } else if (!strcmp(args[1], "uri")) {
2993 if (*(args[2]) == 0) {
2994 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2998 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_ALERT | ERR_ABORT;
3000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
3002 } else if (!strcmp(args[1], "realm")) {
3003 if (*(args[2]) == 0) {
3004 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3008 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_ABORT;
3010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003012 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003013 unsigned interval;
3014
3015 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3016 if (err) {
3017 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3018 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003021 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3022 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_ABORT;
3024 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003025 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003026 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003027 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003028
3029 if (curproxy == &defproxy) {
3030 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
3035 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3036 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3037 err_code |= ERR_ALERT | ERR_ABORT;
3038 goto out;
3039 }
3040
Willy Tarreauff011f22011-01-06 17:51:27 +01003041 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3042 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003043 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3044 file, linenum, args[0]);
3045 err_code |= ERR_WARN;
3046 }
3047
Willy Tarreauff011f22011-01-06 17:51:27 +01003048 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003049
Willy Tarreauff011f22011-01-06 17:51:27 +01003050 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003051 err_code |= ERR_ALERT | ERR_ABORT;
3052 goto out;
3053 }
3054
Willy Tarreauff011f22011-01-06 17:51:27 +01003055 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3056 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 } else if (!strcmp(args[1], "auth")) {
3059 if (*(args[2]) == 0) {
3060 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_ABORT;
3066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 }
3068 } else if (!strcmp(args[1], "scope")) {
3069 if (*(args[2]) == 0) {
3070 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3074 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_ALERT | ERR_ABORT;
3076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 }
3078 } else if (!strcmp(args[1], "enable")) {
3079 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3080 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_ABORT;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003084 } else if (!strcmp(args[1], "hide-version")) {
3085 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3086 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003089 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003090 } else if (!strcmp(args[1], "show-legends")) {
3091 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3092 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
3095 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003096 } else if (!strcmp(args[1], "show-node")) {
3097
3098 if (*args[2]) {
3099 int i;
3100 char c;
3101
3102 for (i=0; args[2][i]; i++) {
3103 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003104 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3105 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003106 break;
3107 }
3108
3109 if (!i || args[2][i]) {
3110 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3111 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3112 file, linenum, args[0], args[1]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116 }
3117
3118 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3119 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3120 err_code |= ERR_ALERT | ERR_ABORT;
3121 goto out;
3122 }
3123 } else if (!strcmp(args[1], "show-desc")) {
3124 char *desc = NULL;
3125
3126 if (*args[2]) {
3127 int i, len=0;
3128 char *d;
3129
3130 for(i=2; *args[i]; i++)
3131 len += strlen(args[i])+1;
3132
3133 desc = d = (char *)calloc(1, len);
3134
3135 d += sprintf(d, "%s", args[2]);
3136 for(i=3; *args[i]; i++)
3137 d += sprintf(d, " %s", args[i]);
3138 }
3139
3140 if (!*args[2] && !global.desc)
3141 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3142 file, linenum, args[1]);
3143 else {
3144 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3145 free(desc);
3146 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3147 err_code |= ERR_ALERT | ERR_ABORT;
3148 goto out;
3149 }
3150 free(desc);
3151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003153stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003154 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 +01003155 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 }
3159 }
3160 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003161 int optnum;
3162
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003163 if (*(args[1]) == '\0') {
3164 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_FATAL;
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003169
3170 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3171 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003172 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3173 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3174 file, linenum, cfg_opts[optnum].name);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
Willy Tarreau93893792009-07-23 13:19:11 +02003178 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3179 err_code |= ERR_WARN;
3180 goto out;
3181 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003182
Willy Tarreau3842f002009-06-14 11:39:52 +02003183 curproxy->no_options &= ~cfg_opts[optnum].val;
3184 curproxy->options &= ~cfg_opts[optnum].val;
3185
3186 switch (kwm) {
3187 case KWM_STD:
3188 curproxy->options |= cfg_opts[optnum].val;
3189 break;
3190 case KWM_NO:
3191 curproxy->no_options |= cfg_opts[optnum].val;
3192 break;
3193 case KWM_DEF: /* already cleared */
3194 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003195 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003196
Willy Tarreau93893792009-07-23 13:19:11 +02003197 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003198 }
3199 }
3200
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003201 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3202 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003203 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3204 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3205 file, linenum, cfg_opts2[optnum].name);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
Willy Tarreau93893792009-07-23 13:19:11 +02003209 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3210 err_code |= ERR_WARN;
3211 goto out;
3212 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003213
Willy Tarreau3842f002009-06-14 11:39:52 +02003214 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3215 curproxy->options2 &= ~cfg_opts2[optnum].val;
3216
3217 switch (kwm) {
3218 case KWM_STD:
3219 curproxy->options2 |= cfg_opts2[optnum].val;
3220 break;
3221 case KWM_NO:
3222 curproxy->no_options2 |= cfg_opts2[optnum].val;
3223 break;
3224 case KWM_DEF: /* already cleared */
3225 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003228 }
3229 }
3230
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 if (kwm != KWM_STD) {
3232 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003233 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003236 }
3237
Emeric Brun3a058f32009-06-30 18:26:00 +02003238 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003239 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003241 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003242 if (*(args[2]) != '\0') {
3243 if (!strcmp(args[2], "clf")) {
3244 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003245 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003246 } else {
3247 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003250 }
3251 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003252 if (curproxy->logformat_string != default_http_log_format &&
3253 curproxy->logformat_string != default_tcp_log_format &&
3254 curproxy->logformat_string != clf_http_log_format)
3255 free(curproxy->logformat_string);
3256 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003257 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003258 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003260 if (curproxy->logformat_string != default_http_log_format &&
3261 curproxy->logformat_string != default_tcp_log_format &&
3262 curproxy->logformat_string != clf_http_log_format)
3263 free(curproxy->logformat_string);
3264 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 else if (!strcmp(args[1], "tcpka")) {
3267 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003270
3271 if (curproxy->cap & PR_CAP_FE)
3272 curproxy->options |= PR_O_TCP_CLI_KA;
3273 if (curproxy->cap & PR_CAP_BE)
3274 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_WARN;
3279
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003281 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003282 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003283 curproxy->options2 &= ~PR_O2_CHK_ANY;
3284 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 if (!*args[2]) { /* no argument */
3286 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3287 curproxy->check_len = strlen(DEF_CHECK_REQ);
3288 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003289 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 curproxy->check_req = (char *)malloc(reqlen);
3291 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003292 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003294 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 if (*args[4])
3296 reqlen += strlen(args[4]);
3297 else
3298 reqlen += strlen("HTTP/1.0");
3299
3300 curproxy->check_req = (char *)malloc(reqlen);
3301 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003302 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003304 }
3305 else if (!strcmp(args[1], "ssl-hello-chk")) {
3306 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003309
Willy Tarreaua534fea2008-08-03 12:19:50 +02003310 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003311 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003312 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003313 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau23677902007-05-08 23:50:35 +02003315 else if (!strcmp(args[1], "smtpchk")) {
3316 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003317 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003318 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003319 curproxy->options2 &= ~PR_O2_CHK_ANY;
3320 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003321
3322 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3323 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3324 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3325 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3326 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3327 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3328 curproxy->check_req = (char *)malloc(reqlen);
3329 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3330 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3331 } else {
3332 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3333 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3334 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3335 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3336 }
3337 }
3338 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003339 else if (!strcmp(args[1], "pgsql-check")) {
3340 /* use PostgreSQL request to check servers' health */
3341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3342 err_code |= ERR_WARN;
3343
3344 free(curproxy->check_req);
3345 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003346 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003347 curproxy->options2 |= PR_O2_PGSQL_CHK;
3348
3349 if (*(args[2])) {
3350 int cur_arg = 2;
3351
3352 while (*(args[cur_arg])) {
3353 if (strcmp(args[cur_arg], "user") == 0) {
3354 char * packet;
3355 uint32_t packet_len;
3356 uint32_t pv;
3357
3358 /* suboption header - needs additional argument for it */
3359 if (*(args[cur_arg+1]) == 0) {
3360 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3361 file, linenum, args[0], args[1], args[cur_arg]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365
3366 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3367 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3368 pv = htonl(0x30000); /* protocol version 3.0 */
3369
3370 packet = (char*) calloc(1, packet_len);
3371
3372 memcpy(packet + 4, &pv, 4);
3373
3374 /* copy "user" */
3375 memcpy(packet + 8, "user", 4);
3376
3377 /* copy username */
3378 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3379
3380 free(curproxy->check_req);
3381 curproxy->check_req = packet;
3382 curproxy->check_len = packet_len;
3383
3384 packet_len = htonl(packet_len);
3385 memcpy(packet, &packet_len, 4);
3386 cur_arg += 2;
3387 } else {
3388 /* unknown suboption - catchall */
3389 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3390 file, linenum, args[0], args[1]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394 } /* end while loop */
3395 }
3396 }
3397
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003398 else if (!strcmp(args[1], "redis-check")) {
3399 /* use REDIS PING request to check servers' health */
3400 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3401 err_code |= ERR_WARN;
3402
3403 free(curproxy->check_req);
3404 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003405 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003406 curproxy->options2 |= PR_O2_REDIS_CHK;
3407
3408 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3409 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3410 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3411 }
3412
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003413 else if (!strcmp(args[1], "mysql-check")) {
3414 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3416 err_code |= ERR_WARN;
3417
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003422
3423 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3424 * const char mysql40_client_auth_pkt[] = {
3425 * "\x0e\x00\x00" // packet length
3426 * "\x01" // packet number
3427 * "\x00\x00" // client capabilities
3428 * "\x00\x00\x01" // max packet
3429 * "haproxy\x00" // username (null terminated string)
3430 * "\x00" // filler (always 0x00)
3431 * "\x01\x00\x00" // packet length
3432 * "\x00" // packet number
3433 * "\x01" // COM_QUIT command
3434 * };
3435 */
3436
3437 if (*(args[2])) {
3438 int cur_arg = 2;
3439
3440 while (*(args[cur_arg])) {
3441 if (strcmp(args[cur_arg], "user") == 0) {
3442 char *mysqluser;
3443 int packetlen, reqlen, userlen;
3444
3445 /* suboption header - needs additional argument for it */
3446 if (*(args[cur_arg+1]) == 0) {
3447 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3448 file, linenum, args[0], args[1], args[cur_arg]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 mysqluser = args[cur_arg + 1];
3453 userlen = strlen(mysqluser);
3454 packetlen = userlen + 7;
3455 reqlen = packetlen + 9;
3456
3457 free(curproxy->check_req);
3458 curproxy->check_req = (char *)calloc(1, reqlen);
3459 curproxy->check_len = reqlen;
3460
3461 snprintf(curproxy->check_req, 4, "%c%c%c",
3462 ((unsigned char) packetlen & 0xff),
3463 ((unsigned char) (packetlen >> 8) & 0xff),
3464 ((unsigned char) (packetlen >> 16) & 0xff));
3465
3466 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003467 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003468 curproxy->check_req[8] = 1;
3469 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3470 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3471 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3472 cur_arg += 2;
3473 } else {
3474 /* unknown suboption - catchall */
3475 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3476 file, linenum, args[0], args[1]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480 } /* end while loop */
3481 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003482 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003483 else if (!strcmp(args[1], "ldap-check")) {
3484 /* use LDAP request to check servers' health */
3485 free(curproxy->check_req);
3486 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003487 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003488 curproxy->options2 |= PR_O2_LDAP_CHK;
3489
3490 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3491 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3492 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3493 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003494 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003495 int cur_arg;
3496
3497 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3498 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003499 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003500
Willy Tarreau87cf5142011-08-19 22:57:24 +02003501 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003502
3503 free(curproxy->fwdfor_hdr_name);
3504 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3505 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3506
3507 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3508 cur_arg = 2;
3509 while (*(args[cur_arg])) {
3510 if (!strcmp(args[cur_arg], "except")) {
3511 /* suboption except - needs additional argument for it */
3512 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3513 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3514 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003517 }
3518 /* flush useless bits */
3519 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003520 cur_arg += 2;
3521 } else if (!strcmp(args[cur_arg], "header")) {
3522 /* suboption header - needs additional argument for it */
3523 if (*(args[cur_arg+1]) == 0) {
3524 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003528 }
3529 free(curproxy->fwdfor_hdr_name);
3530 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3531 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3532 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003533 } else if (!strcmp(args[cur_arg], "if-none")) {
3534 curproxy->options &= ~PR_O_FF_ALWAYS;
3535 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003536 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003538 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003539 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003542 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003544 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003545 else if (!strcmp(args[1], "originalto")) {
3546 int cur_arg;
3547
3548 /* insert x-original-to field, but not for the IP address listed as an except.
3549 * set default options (ie: bitfield, header name, etc)
3550 */
3551
3552 curproxy->options |= PR_O_ORGTO;
3553
3554 free(curproxy->orgto_hdr_name);
3555 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3556 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3557
Willy Tarreau87cf5142011-08-19 22:57:24 +02003558 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003559 cur_arg = 2;
3560 while (*(args[cur_arg])) {
3561 if (!strcmp(args[cur_arg], "except")) {
3562 /* suboption except - needs additional argument for it */
3563 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3564 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3565 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003568 }
3569 /* flush useless bits */
3570 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3571 cur_arg += 2;
3572 } else if (!strcmp(args[cur_arg], "header")) {
3573 /* suboption header - needs additional argument for it */
3574 if (*(args[cur_arg+1]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003579 }
3580 free(curproxy->orgto_hdr_name);
3581 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3582 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3583 cur_arg += 2;
3584 } else {
3585 /* unknown suboption - catchall */
3586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003590 }
3591 } /* end while loop */
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else {
3594 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
Willy Tarreau93893792009-07-23 13:19:11 +02003598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003600 else if (!strcmp(args[0], "default_backend")) {
3601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003603
3604 if (*(args[1]) == 0) {
3605 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003608 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003609 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003610 curproxy->defbe.name = strdup(args[1]);
3611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003616 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 /* enable reconnections to dispatch */
3620 curproxy->options |= PR_O_REDISP;
3621 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003622 else if (!strcmp(args[0], "http-check")) {
3623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003625
3626 if (strcmp(args[1], "disable-on-404") == 0) {
3627 /* enable a graceful server shutdown on an HTTP 404 response */
3628 curproxy->options |= PR_O_DISABLE404;
3629 }
Willy Tarreauef781042010-01-27 11:53:01 +01003630 else if (strcmp(args[1], "send-state") == 0) {
3631 /* enable emission of the apparent state of a server in HTTP checks */
3632 curproxy->options2 |= PR_O2_CHK_SNDST;
3633 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003634 else if (strcmp(args[1], "expect") == 0) {
3635 const char *ptr_arg;
3636 int cur_arg;
3637
3638 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3639 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
3642 }
3643
3644 cur_arg = 2;
3645 /* consider exclamation marks, sole or at the beginning of a word */
3646 while (*(ptr_arg = args[cur_arg])) {
3647 while (*ptr_arg == '!') {
3648 curproxy->options2 ^= PR_O2_EXP_INV;
3649 ptr_arg++;
3650 }
3651 if (*ptr_arg)
3652 break;
3653 cur_arg++;
3654 }
3655 /* now ptr_arg points to the beginning of a word past any possible
3656 * exclamation mark, and cur_arg is the argument which holds this word.
3657 */
3658 if (strcmp(ptr_arg, "status") == 0) {
3659 if (!*(args[cur_arg + 1])) {
3660 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3661 file, linenum, args[0], args[1], ptr_arg);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003666 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003667 curproxy->expect_str = strdup(args[cur_arg + 1]);
3668 }
3669 else if (strcmp(ptr_arg, "string") == 0) {
3670 if (!*(args[cur_arg + 1])) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3672 file, linenum, args[0], args[1], ptr_arg);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003677 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003678 curproxy->expect_str = strdup(args[cur_arg + 1]);
3679 }
3680 else if (strcmp(ptr_arg, "rstatus") == 0) {
3681 if (!*(args[cur_arg + 1])) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3683 file, linenum, args[0], args[1], ptr_arg);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
3687 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003688 free(curproxy->expect_str);
3689 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3690 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003691 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3692 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3693 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3694 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 }
3699 else if (strcmp(ptr_arg, "rstring") == 0) {
3700 if (!*(args[cur_arg + 1])) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3702 file, linenum, args[0], args[1], ptr_arg);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003707 free(curproxy->expect_str);
3708 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3709 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003710 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3711 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3713 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 }
3718 else {
3719 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3720 file, linenum, args[0], args[1], ptr_arg);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003725 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003726 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 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003729 }
3730 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003731 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003736 }
3737
Willy Tarreaub80c2302007-11-30 20:51:32 +01003738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740
3741 if (strcmp(args[1], "fail") == 0) {
3742 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003743 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003744 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 }
3749
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003750 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3751 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3752 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003755 }
3756 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3757 }
3758 else {
3759 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003762 }
3763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764#ifdef TPROXY
3765 else if (!strcmp(args[0], "transparent")) {
3766 /* enable transparent proxy connections */
3767 curproxy->options |= PR_O_TRANSP;
3768 }
3769#endif
3770 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003773
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 if (*(args[1]) == 0) {
3775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 curproxy->maxconn = atol(args[1]);
3780 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003781 else if (!strcmp(args[0], "backlog")) { /* backlog */
3782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003784
3785 if (*(args[1]) == 0) {
3786 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003789 }
3790 curproxy->backlog = atol(args[1]);
3791 }
Willy Tarreau86034312006-12-29 00:10:33 +01003792 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003795
Willy Tarreau86034312006-12-29 00:10:33 +01003796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003800 }
3801 curproxy->fullconn = atol(args[1]);
3802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3804 if (*(args[1]) == 0) {
3805 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003809 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3810 if (err) {
3811 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3812 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003815 }
3816 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003819 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003825 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 if (strchr(args[1], ':') == NULL) {
3829 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003833 sk = str2sa(args[1]);
3834 if (!sk) {
3835 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003845
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003846 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3847 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003852 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3854 err_code |= ERR_WARN;
3855
3856 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3857 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3858 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3859 }
3860 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3861 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3862 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3863 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003864 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3865 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3866 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3867 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003868 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003869 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
3872 }
3873 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003874 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003876 char *rport, *raddr;
3877 short realport = 0;
3878 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003885 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887
3888 if (!*args[2]) {
3889 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003894
3895 err = invalid_char(args[1]);
3896 if (err) {
3897 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3898 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003901 }
3902
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003903 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003904 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003905
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003906 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3907 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3908 err_code |= ERR_ALERT | ERR_ABORT;
3909 goto out;
3910 }
3911
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 /* the servers are linked backwards first */
3913 newsrv->next = curproxy->srv;
3914 curproxy->srv = newsrv;
3915 newsrv->proxy = curproxy;
3916 newsrv->conf.file = file;
3917 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918
Simon Hormanaf514952011-06-21 14:34:57 +09003919 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 LIST_INIT(&newsrv->pendconns);
3921 do_check = 0;
3922 newsrv->state = SRV_RUNNING; /* early server setup */
3923 newsrv->last_change = now.tv_sec;
3924 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003927 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 * - IP: => port=+0, relative
3929 * - IP:N => port=N, absolute
3930 * - IP:+N => port=+N, relative
3931 * - IP:-N => port=-N, relative
3932 */
3933 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003934 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003935 if (rport) {
3936 *rport++ = 0;
3937 realport = atol(rport);
3938 if (!isdigit((unsigned char)*rport))
3939 newsrv->state |= SRV_MAPPORTS;
3940 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003942
Willy Tarreaufab5a432011-03-04 15:31:53 +01003943 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003945 if (!sk) {
3946 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
3949 }
3950 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003951 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02003952 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003953
Willy Tarreau173e7fb2012-09-24 22:47:39 +02003954 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02003955 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
3956 file, linenum, newsrv->addr.ss_family, args[2]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003960 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961
3962 newsrv->check_port = curproxy->defsrv.check_port;
3963 newsrv->inter = curproxy->defsrv.inter;
3964 newsrv->fastinter = curproxy->defsrv.fastinter;
3965 newsrv->downinter = curproxy->defsrv.downinter;
3966 newsrv->rise = curproxy->defsrv.rise;
3967 newsrv->fall = curproxy->defsrv.fall;
3968 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3969 newsrv->minconn = curproxy->defsrv.minconn;
3970 newsrv->maxconn = curproxy->defsrv.maxconn;
3971 newsrv->slowstart = curproxy->defsrv.slowstart;
3972 newsrv->onerror = curproxy->defsrv.onerror;
3973 newsrv->consecutive_errors_limit
3974 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02003975#ifdef OPENSSL
3976 newsrv->use_ssl = curproxy->defsrv.use_ssl;
3977#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003978 newsrv->uweight = newsrv->iweight
3979 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003981 newsrv->curfd = -1; /* no health-check in progress */
3982 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 cur_arg = 3;
3985 } else {
3986 newsrv = &curproxy->defsrv;
3987 cur_arg = 1;
3988 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003989
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003991 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003992 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003993
3994 if (!*args[cur_arg + 1]) {
3995 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3996 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999 }
4000
4001 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004002 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004003
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004004 if (newsrv->puid <= 0) {
4005 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004006 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004009 }
4010
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004011 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4012 if (node) {
4013 struct server *target = container_of(node, struct server, conf.id);
4014 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4015 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004020 cur_arg += 2;
4021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 newsrv->cookie = strdup(args[cur_arg + 1]);
4024 newsrv->cklen = strlen(args[cur_arg + 1]);
4025 cur_arg += 2;
4026 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004028 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4029 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4030 cur_arg += 2;
4031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004033 if (!*args[cur_arg + 1]) {
4034 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4035 file, linenum, args[cur_arg]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004041 if (newsrv->rise <= 0) {
4042 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4043 file, linenum, args[cur_arg]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
Willy Tarreau96839092010-03-29 10:02:24 +02004048 if (newsrv->health)
4049 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 cur_arg += 2;
4051 }
4052 else if (!strcmp(args[cur_arg], "fall")) {
4053 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004054
4055 if (!*args[cur_arg + 1]) {
4056 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4057 file, linenum, args[cur_arg]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
4062 if (newsrv->fall <= 0) {
4063 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4064 file, linenum, args[cur_arg]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 cur_arg += 2;
4070 }
4071 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004072 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4073 if (err) {
4074 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4075 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004078 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004079 if (val <= 0) {
4080 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4081 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004084 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004085 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 cur_arg += 2;
4087 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004088 else if (!strcmp(args[cur_arg], "fastinter")) {
4089 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4090 if (err) {
4091 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4092 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004095 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004096 if (val <= 0) {
4097 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4098 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 newsrv->fastinter = val;
4103 cur_arg += 2;
4104 }
4105 else if (!strcmp(args[cur_arg], "downinter")) {
4106 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4107 if (err) {
4108 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4109 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004112 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004113 if (val <= 0) {
4114 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4115 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004118 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 newsrv->downinter = val;
4120 cur_arg += 2;
4121 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004123 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004124 if (!sk) {
4125 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004130 cur_arg += 2;
4131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 else if (!strcmp(args[cur_arg], "port")) {
4133 newsrv->check_port = atol(args[cur_arg + 1]);
4134 cur_arg += 2;
4135 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 newsrv->state |= SRV_BACKUP;
4138 cur_arg ++;
4139 }
Simon Hormanfa461682011-06-25 09:39:49 +09004140 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4141 newsrv->state |= SRV_NON_STICK;
4142 cur_arg ++;
4143 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004144 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4145 newsrv->state |= SRV_SEND_PROXY;
4146 cur_arg ++;
4147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 else if (!strcmp(args[cur_arg], "weight")) {
4149 int w;
4150 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004151 if (w < 0 || w > 256) {
4152 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004157 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 cur_arg += 2;
4159 }
4160 else if (!strcmp(args[cur_arg], "minconn")) {
4161 newsrv->minconn = atol(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
4164 else if (!strcmp(args[cur_arg], "maxconn")) {
4165 newsrv->maxconn = atol(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004168 else if (!strcmp(args[cur_arg], "maxqueue")) {
4169 newsrv->maxqueue = atol(args[cur_arg + 1]);
4170 cur_arg += 2;
4171 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004172 else if (!strcmp(args[cur_arg], "slowstart")) {
4173 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004174 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004175 if (err) {
4176 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4177 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004180 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004181 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004182 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4183 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004186 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004187 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004188 cur_arg += 2;
4189 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004190 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004191
4192 if (!*args[cur_arg + 1]) {
4193 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4194 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004197 }
4198
4199 newsrv->trackit = strdup(args[cur_arg + 1]);
4200
4201 cur_arg += 2;
4202 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004203 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 global.maxsock++;
4205 do_check = 1;
4206 cur_arg += 1;
4207 }
Willy Tarreau96839092010-03-29 10:02:24 +02004208 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4209 newsrv->state |= SRV_MAINTAIN;
4210 newsrv->state &= ~SRV_RUNNING;
4211 newsrv->health = 0;
4212 cur_arg += 1;
4213 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004214 else if (!strcmp(args[cur_arg], "ssl")) {
4215#ifdef USE_OPENSSL
4216 newsrv->use_ssl = 1;
4217 cur_arg += 1;
4218#else /* USE_OPENSSL */
4219 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4220 file, linenum, args[cur_arg]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223#endif /* USE_OPENSSL */
4224 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004225 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4226#ifdef USE_OPENSSL
4227 if (!*args[cur_arg + 1]) {
4228 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4229 file, linenum, args[0], args[cur_arg]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
4234 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4235
4236 cur_arg += 2;
4237 continue;
4238#else
4239 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4240 file, linenum, args[0], args[cur_arg]);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243#endif
4244 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004245 else if (!strcmp(args[cur_arg], "nosslv3")) {
4246#ifdef USE_OPENSSL
4247 newsrv->ssl_ctx.nosslv3 = 1;
4248 cur_arg += 1;
4249#else /* USE_OPENSSL */
4250 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4251 file, linenum, args[cur_arg]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254#endif /* USE_OPENSSL */
4255 }
4256 else if (!strcmp(args[cur_arg], "notlsv1")) {
4257#ifdef USE_OPENSSL
4258 newsrv->ssl_ctx.notlsv1 = 1;
4259 cur_arg += 1;
4260#else /* USE_OPENSSL */
4261 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4262 file, linenum, args[cur_arg]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265#endif /* USE_OPENSSL */
4266 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004267 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004268 if (!strcmp(args[cur_arg + 1], "none"))
4269 newsrv->observe = HANA_OBS_NONE;
4270 else if (!strcmp(args[cur_arg + 1], "layer4"))
4271 newsrv->observe = HANA_OBS_LAYER4;
4272 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4273 if (curproxy->mode != PR_MODE_HTTP) {
4274 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4275 file, linenum, args[cur_arg + 1]);
4276 err_code |= ERR_ALERT;
4277 }
4278 newsrv->observe = HANA_OBS_LAYER7;
4279 }
4280 else {
4281 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004282 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004283 file, linenum, args[cur_arg], args[cur_arg + 1]);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287
4288 cur_arg += 2;
4289 }
4290 else if (!strcmp(args[cur_arg], "on-error")) {
4291 if (!strcmp(args[cur_arg + 1], "fastinter"))
4292 newsrv->onerror = HANA_ONERR_FASTINTER;
4293 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4294 newsrv->onerror = HANA_ONERR_FAILCHK;
4295 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4296 newsrv->onerror = HANA_ONERR_SUDDTH;
4297 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4298 newsrv->onerror = HANA_ONERR_MARKDWN;
4299 else {
4300 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004301 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004302 file, linenum, args[cur_arg], args[cur_arg + 1]);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306
4307 cur_arg += 2;
4308 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004309 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4310 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4311 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4312 else {
4313 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4314 file, linenum, args[cur_arg], args[cur_arg + 1]);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318
4319 cur_arg += 2;
4320 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004321 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4322 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4323 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4324 else {
4325 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4326 file, linenum, args[cur_arg], args[cur_arg + 1]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330
4331 cur_arg += 2;
4332 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004333 else if (!strcmp(args[cur_arg], "error-limit")) {
4334 if (!*args[cur_arg + 1]) {
4335 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4336 file, linenum, args[cur_arg]);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340
4341 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4342
4343 if (newsrv->consecutive_errors_limit <= 0) {
4344 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4345 file, linenum, args[cur_arg]);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004349 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004350 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004351 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004352 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004353 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004354
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004356#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004357 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004358 file, linenum, "source", "usesrc");
4359#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004360 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004362#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004365 }
4366 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004367 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4368 if (!sk) {
4369 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004374
4375 if (port_low != port_high) {
4376 int i;
4377 if (port_low <= 0 || port_low > 65535 ||
4378 port_high <= 0 || port_high > 65535 ||
4379 port_low > port_high) {
4380 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4381 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004384 }
4385 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4386 for (i = 0; i < newsrv->sport_range->size; i++)
4387 newsrv->sport_range->ports[i] = port_low + i;
4388 }
4389
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 while (*(args[cur_arg])) {
4392 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004393#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4394#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4396 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4397 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004401#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004403 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407 }
4408 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004409 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004410 newsrv->state |= SRV_TPROXY_CLI;
4411 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004412 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004414 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4415 char *name, *end;
4416
4417 name = args[cur_arg+1] + 7;
4418 while (isspace(*name))
4419 name++;
4420
4421 end = name;
4422 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4423 end++;
4424
4425 newsrv->state &= ~SRV_TPROXY_MASK;
4426 newsrv->state |= SRV_TPROXY_DYN;
4427 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4428 newsrv->bind_hdr_len = end - name;
4429 memcpy(newsrv->bind_hdr_name, name, end - name);
4430 newsrv->bind_hdr_name[end-name] = '\0';
4431 newsrv->bind_hdr_occ = -1;
4432
4433 /* now look for an occurrence number */
4434 while (isspace(*end))
4435 end++;
4436 if (*end == ',') {
4437 end++;
4438 name = end;
4439 if (*end == '-')
4440 end++;
4441 while (isdigit(*end))
4442 end++;
4443 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4444 }
4445
4446 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4447 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4448 " occurrences values smaller than %d.\n",
4449 file, linenum, MAX_HDR_HISTORY);
4450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
4452 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004453 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004454 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004455 if (!sk) {
4456 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
4460 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004461 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004462 }
4463 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004464#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004466#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004467 cur_arg += 2;
4468 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004469#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004470 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004471 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004474#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4475 } /* "usesrc" */
4476
4477 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4478#ifdef SO_BINDTODEVICE
4479 if (!*args[cur_arg + 1]) {
4480 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 }
4485 if (newsrv->iface_name)
4486 free(newsrv->iface_name);
4487
4488 newsrv->iface_name = strdup(args[cur_arg + 1]);
4489 newsrv->iface_len = strlen(newsrv->iface_name);
4490 global.last_checks |= LSTCHK_NETADM;
4491#else
4492 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4493 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004496#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004497 cur_arg += 2;
4498 continue;
4499 }
4500 /* this keyword in not an option of "source" */
4501 break;
4502 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004504 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004505 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4506 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004511 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004512 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 +01004513 file, linenum, newsrv->id);
4514 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004515 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 +01004516 file, linenum);
4517
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
4521 }
4522
4523 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004524 if (newsrv->trackit) {
4525 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4526 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004529 }
4530
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004531 /* try to get the port from check_addr if check_port not set */
4532 if (!newsrv->check_port)
4533 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004534
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4536 newsrv->check_port = realport; /* by default */
4537 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004538 /* not yet valid, because no port was set on
4539 * the server either. We'll check if we have
4540 * a known port on the first listener.
4541 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004542 struct listener *l;
4543
4544 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
4545 newsrv->check_port = get_host_port(&l->addr);
4546 if (newsrv->check_port)
4547 break;
4548 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004549 }
4550 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4552 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004556
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004557 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004558 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004559 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4560 err_code |= ERR_ALERT | ERR_ABORT;
4561 goto out;
4562 }
4563
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004564 /* Allocate buffer for partial check results... */
4565 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4566 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4567 err_code |= ERR_ALERT | ERR_ABORT;
4568 goto out;
4569 }
4570
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004571 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 newsrv->state |= SRV_CHECKED;
4573 }
4574
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004575 if (!defsrv) {
4576 if (newsrv->state & SRV_BACKUP)
4577 curproxy->srv_bck++;
4578 else
4579 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004580
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004581 newsrv->prev_state = newsrv->state;
4582 }
William Lallemanda73203e2012-03-12 12:48:57 +01004583 }
4584
4585 else if (strcmp(args[0], "unique-id-format") == 0) {
4586 if (!*(args[1])) {
4587 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004591 free(curproxy->uniqueid_format_string);
4592 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004593 }
William Lallemanda73203e2012-03-12 12:48:57 +01004594
4595 else if (strcmp(args[0], "unique-id-header") == 0) {
4596 if (!*(args[1])) {
4597 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601 free(curproxy->header_unique_id);
4602 curproxy->header_unique_id = strdup(args[1]);
4603 }
4604
William Lallemand723b73a2012-02-08 16:37:49 +01004605 else if (strcmp(args[0], "log-format") == 0) {
4606 if (!*(args[1])) {
4607 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004611
4612 if (curproxy->logformat_string != default_http_log_format &&
4613 curproxy->logformat_string != default_tcp_log_format &&
4614 curproxy->logformat_string != clf_http_log_format)
4615 free(curproxy->logformat_string);
4616 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
William Lallemand723b73a2012-02-08 16:37:49 +01004618
William Lallemand0f99e342011-10-12 17:50:54 +02004619 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4620 /* delete previous herited or defined syslog servers */
4621 struct logsrv *back;
4622
4623 if (*(args[1]) != 0) {
4624 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
4627 }
4628
William Lallemand723b73a2012-02-08 16:37:49 +01004629 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4630 LIST_DEL(&tmplogsrv->list);
4631 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004632 }
4633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004635 struct logsrv *logsrv;
4636
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004638 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004639 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004640 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004641 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004642 LIST_INIT(&node->list);
4643 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004645 }
4646 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004647
4648 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649
William Lallemand0f99e342011-10-12 17:50:54 +02004650 logsrv->facility = get_log_facility(args[2]);
4651 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
4657
William Lallemand0f99e342011-10-12 17:50:54 +02004658 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004660 logsrv->level = get_log_level(args[3]);
4661 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
4667 }
4668
William Lallemand0f99e342011-10-12 17:50:54 +02004669 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004670 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004671 logsrv->minlvl = get_log_level(args[4]);
4672 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004673 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004677 }
4678 }
4679
Robert Tsai81ae1952007-12-05 10:47:29 +01004680 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004681 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004682 if (!sk) {
4683 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004684 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
William Lallemand0f99e342011-10-12 17:50:54 +02004688 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004689 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004690 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004691 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004692 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
William Lallemand0f99e342011-10-12 17:50:54 +02004696 logsrv->addr = *sk;
4697 if (!get_host_port(&logsrv->addr))
4698 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
William Lallemand0f99e342011-10-12 17:50:54 +02004700
4701 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
4703 else {
4704 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4705 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 }
4709 }
4710 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004711 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004712 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004713
Willy Tarreau977b8e42006-12-29 14:19:17 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004718 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4719 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004723
4724 /* we must first clear any optional default setting */
4725 curproxy->options &= ~PR_O_TPXY_MASK;
4726 free(curproxy->iface_name);
4727 curproxy->iface_name = NULL;
4728 curproxy->iface_len = 0;
4729
Willy Tarreaud5191e72010-02-09 20:50:45 +01004730 sk = str2sa(args[1]);
4731 if (!sk) {
4732 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
4735 }
4736 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004738
4739 cur_arg = 2;
4740 while (*(args[cur_arg])) {
4741 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004742#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4743#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004744 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4745 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4746 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004749 }
4750#endif
4751 if (!*args[cur_arg + 1]) {
4752 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4753 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 }
4757
4758 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004759 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004760 curproxy->options |= PR_O_TPXY_CLI;
4761 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004762 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004763 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004764 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4765 char *name, *end;
4766
4767 name = args[cur_arg+1] + 7;
4768 while (isspace(*name))
4769 name++;
4770
4771 end = name;
4772 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4773 end++;
4774
4775 curproxy->options &= ~PR_O_TPXY_MASK;
4776 curproxy->options |= PR_O_TPXY_DYN;
4777 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4778 curproxy->bind_hdr_len = end - name;
4779 memcpy(curproxy->bind_hdr_name, name, end - name);
4780 curproxy->bind_hdr_name[end-name] = '\0';
4781 curproxy->bind_hdr_occ = -1;
4782
4783 /* now look for an occurrence number */
4784 while (isspace(*end))
4785 end++;
4786 if (*end == ',') {
4787 end++;
4788 name = end;
4789 if (*end == '-')
4790 end++;
4791 while (isdigit(*end))
4792 end++;
4793 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4794 }
4795
4796 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4797 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4798 " occurrences values smaller than %d.\n",
4799 file, linenum, MAX_HDR_HISTORY);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004804 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004805 if (!sk) {
4806 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
4810 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004811 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004812 }
4813 global.last_checks |= LSTCHK_NETADM;
4814#if !defined(CONFIG_HAP_LINUX_TPROXY)
4815 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004816#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004817#else /* no TPROXY support */
4818 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004819 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004822#endif
4823 cur_arg += 2;
4824 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004825 }
4826
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004827 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4828#ifdef SO_BINDTODEVICE
4829 if (!*args[cur_arg + 1]) {
4830 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4831 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 }
4835 if (curproxy->iface_name)
4836 free(curproxy->iface_name);
4837
4838 curproxy->iface_name = strdup(args[cur_arg + 1]);
4839 curproxy->iface_len = strlen(curproxy->iface_name);
4840 global.last_checks |= LSTCHK_NETADM;
4841#else
4842 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4843 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004846#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004847 cur_arg += 2;
4848 continue;
4849 }
4850 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004851 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004856 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4857 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4858 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004863 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4865 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004869
4870 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004871 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004872 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004873 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 }
4876 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004877 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004878 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004879 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
4883 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004884 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004885 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004886 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004887 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 }
4890 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004892 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004893 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004894 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
4897 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004898 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004899 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004900 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004904 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004906 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004907 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004909 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004910 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004911 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004913 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004914 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004916 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004917 }
4918 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004920 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004921 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004923 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932
4933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004941 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004967 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004975 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004976
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 if (curproxy == &defproxy) {
4978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004982 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (*(args[1]) == 0) {
4986 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004990
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004991 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004992 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
4993 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
4994 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4999 }
5000 else if (*args[2]) {
5001 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5002 file, linenum, args[0], args[2]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
5006
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005007 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005008 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005009 wl->s = strdup(args[1]);
5010 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005011 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 }
5013 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005014 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005020
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005022 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005023 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
5027 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005029 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005030 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
5034 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005036 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005037 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
5041 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 }
5048
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005050 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005051 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
5055 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005057 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005058 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
5062 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005064 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005065 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
5069 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005070 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005071
Willy Tarreaubaaee002006-06-26 02:48:02 +02005072 if (curproxy == &defproxy) {
5073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005077 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 if (*(args[1]) == 0) {
5081 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 }
5085
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005086 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005087 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5088 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5089 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
5092 }
5093 err_code |= warnif_cond_requires_req(cond, file, linenum);
5094 }
5095 else if (*args[2]) {
5096 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5097 file, linenum, args[0], args[2]);
5098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
5100 }
5101
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005102 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005103 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005104 wl->s = strdup(args[1]);
5105 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107 else if (!strcmp(args[0], "errorloc") ||
5108 !strcmp(args[0], "errorloc302") ||
5109 !strcmp(args[0], "errorloc303")) { /* error location */
5110 int errnum, errlen;
5111 char *err;
5112
Willy Tarreau977b8e42006-12-29 14:19:17 +01005113 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005115
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005117 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
5121
5122 errnum = atol(args[1]);
5123 if (!strcmp(args[0], "errorloc303")) {
5124 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5125 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5126 } else {
5127 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5128 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5129 }
5130
Willy Tarreau0f772532006-12-23 20:51:41 +01005131 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5132 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005133 chunk_destroy(&curproxy->errmsg[rc]);
5134 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005135 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005138
5139 if (rc >= HTTP_ERR_SIZE) {
5140 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5141 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 free(err);
5143 }
5144 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005145 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5146 int errnum, errlen, fd;
5147 char *err;
5148 struct stat stat;
5149
5150 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005151 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005152
5153 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005154 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005157 }
5158
5159 fd = open(args[2], O_RDONLY);
5160 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5161 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5162 file, linenum, args[2], args[1]);
5163 if (fd >= 0)
5164 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005167 }
5168
Willy Tarreau27a674e2009-08-17 07:23:33 +02005169 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005170 errlen = stat.st_size;
5171 } else {
5172 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005173 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005175 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005176 }
5177
5178 err = malloc(errlen); /* malloc() must succeed during parsing */
5179 errnum = read(fd, err, errlen);
5180 if (errnum != errlen) {
5181 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5182 file, linenum, args[2], args[1]);
5183 close(fd);
5184 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005187 }
5188 close(fd);
5189
5190 errnum = atol(args[1]);
5191 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5192 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005193 chunk_destroy(&curproxy->errmsg[rc]);
5194 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005195 break;
5196 }
5197 }
5198
5199 if (rc >= HTTP_ERR_SIZE) {
5200 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5201 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005202 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005203 free(err);
5204 }
5205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005207 struct cfg_kw_list *kwl;
5208 int index;
5209
5210 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5211 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5212 if (kwl->kw[index].section != CFG_LISTEN)
5213 continue;
5214 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5215 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005216 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005217 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005218 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005219 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005220 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005223 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005224 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005225 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_WARN;
5227 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005228 }
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005230 }
5231 }
5232 }
5233
Willy Tarreau6daf3432008-01-22 16:44:08 +01005234 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
Willy Tarreau93893792009-07-23 13:19:11 +02005238 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005239 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241}
5242
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005243int
5244cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5245{
5246
5247 int err_code = 0;
5248 const char *err;
5249
5250 if (!strcmp(args[0], "userlist")) { /* new userlist */
5251 struct userlist *newul;
5252
5253 if (!*args[1]) {
5254 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5255 file, linenum, args[0]);
5256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
5258 }
5259
5260 err = invalid_char(args[1]);
5261 if (err) {
5262 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5263 file, linenum, *err, args[0], args[1]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
5267
5268 for (newul = userlist; newul; newul = newul->next)
5269 if (!strcmp(newul->name, args[1])) {
5270 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5271 file, linenum, args[1]);
5272 err_code |= ERR_WARN;
5273 goto out;
5274 }
5275
5276 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5277 if (!newul) {
5278 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5279 err_code |= ERR_ALERT | ERR_ABORT;
5280 goto out;
5281 }
5282
5283 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5284 newul->name = strdup(args[1]);
5285
5286 if (!newul->groupusers | !newul->name) {
5287 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5288 err_code |= ERR_ALERT | ERR_ABORT;
5289 goto out;
5290 }
5291
5292 newul->next = userlist;
5293 userlist = newul;
5294
5295 } else if (!strcmp(args[0], "group")) { /* new group */
5296 int cur_arg, i;
5297 const char *err;
5298
5299 if (!*args[1]) {
5300 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5301 file, linenum, args[0]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
5305
5306 err = invalid_char(args[1]);
5307 if (err) {
5308 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5309 file, linenum, *err, args[0], args[1]);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313
5314 for(i = 0; i < userlist->grpcnt; i++)
5315 if (!strcmp(userlist->groups[i], args[1])) {
5316 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5317 file, linenum, args[1], userlist->name);
5318 err_code |= ERR_ALERT;
5319 goto out;
5320 }
5321
5322 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5323 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5324 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
5328
5329 cur_arg = 2;
5330
5331 while (*args[cur_arg]) {
5332 if (!strcmp(args[cur_arg], "users")) {
5333 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5334 cur_arg += 2;
5335 continue;
5336 } else {
5337 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5338 file, linenum, args[0]);
5339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
5341 }
5342 }
5343
5344 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5345 } else if (!strcmp(args[0], "user")) { /* new user */
5346 struct auth_users *newuser;
5347 int cur_arg;
5348
5349 if (!*args[1]) {
5350 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5351 file, linenum, args[0]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355
5356 for (newuser = userlist->users; newuser; newuser = newuser->next)
5357 if (!strcmp(newuser->user, args[1])) {
5358 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5359 file, linenum, args[1], userlist->name);
5360 err_code |= ERR_ALERT;
5361 goto out;
5362 }
5363
5364 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5365 if (!newuser) {
5366 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5367 err_code |= ERR_ALERT | ERR_ABORT;
5368 goto out;
5369 }
5370
5371 newuser->user = strdup(args[1]);
5372
5373 newuser->next = userlist->users;
5374 userlist->users = newuser;
5375
5376 cur_arg = 2;
5377
5378 while (*args[cur_arg]) {
5379 if (!strcmp(args[cur_arg], "password")) {
5380#ifndef CONFIG_HAP_CRYPT
5381 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5382 file, linenum);
5383 err_code |= ERR_ALERT;
5384#endif
5385 newuser->pass = strdup(args[cur_arg + 1]);
5386 cur_arg += 2;
5387 continue;
5388 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5389 newuser->pass = strdup(args[cur_arg + 1]);
5390 newuser->flags |= AU_O_INSECURE;
5391 cur_arg += 2;
5392 continue;
5393 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005394 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005395 cur_arg += 2;
5396 continue;
5397 } else {
5398 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5399 file, linenum, args[0]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403 }
5404 } else {
5405 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5406 err_code |= ERR_ALERT | ERR_FATAL;
5407 }
5408
5409out:
5410 return err_code;
5411}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412
5413/*
5414 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005415 * Returns the error code, 0 if OK, or any combination of :
5416 * - ERR_ABORT: must abort ASAP
5417 * - ERR_FATAL: we can continue parsing but not start the service
5418 * - ERR_WARN: a warning has been emitted
5419 * - ERR_ALERT: an alert has been emitted
5420 * Only the two first ones can stop processing, the two others are just
5421 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005423int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005425 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005426 FILE *f;
5427 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005429 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 if ((f=fopen(file,"r")) == NULL)
5432 return -1;
5433
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005434 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005435 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005436 char *end;
5437 char *args[MAX_LINE_ARGS + 1];
5438 char *line = thisline;
5439
Willy Tarreaubaaee002006-06-26 02:48:02 +02005440 linenum++;
5441
5442 end = line + strlen(line);
5443
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005444 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5445 /* Check if we reached the limit and the last char is not \n.
5446 * Watch out for the last line without the terminating '\n'!
5447 */
5448 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005449 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005450 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005451 }
5452
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005454 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 line++;
5456
5457 arg = 0;
5458 args[arg] = line;
5459
5460 while (*line && arg < MAX_LINE_ARGS) {
5461 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5462 * C equivalent value. Other combinations left unchanged (eg: \1).
5463 */
5464 if (*line == '\\') {
5465 int skip = 0;
5466 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5467 *line = line[1];
5468 skip = 1;
5469 }
5470 else if (line[1] == 'r') {
5471 *line = '\r';
5472 skip = 1;
5473 }
5474 else if (line[1] == 'n') {
5475 *line = '\n';
5476 skip = 1;
5477 }
5478 else if (line[1] == 't') {
5479 *line = '\t';
5480 skip = 1;
5481 }
5482 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005483 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 unsigned char hex1, hex2;
5485 hex1 = toupper(line[2]) - '0';
5486 hex2 = toupper(line[3]) - '0';
5487 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5488 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5489 *line = (hex1<<4) + hex2;
5490 skip = 3;
5491 }
5492 else {
5493 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005494 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
5496 }
5497 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005498 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 end -= skip;
5500 }
5501 line++;
5502 }
5503 else if (*line == '#' || *line == '\n' || *line == '\r') {
5504 /* end of string, end of loop */
5505 *line = 0;
5506 break;
5507 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005508 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005510 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005511 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 line++;
5513 args[++arg] = line;
5514 }
5515 else {
5516 line++;
5517 }
5518 }
5519
5520 /* empty line */
5521 if (!**args)
5522 continue;
5523
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005524 if (*line) {
5525 /* we had to stop due to too many args.
5526 * Let's terminate the string, print the offending part then cut the
5527 * last arg.
5528 */
5529 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5530 line++;
5531 *line = '\0';
5532
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005533 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005534 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005535 err_code |= ERR_ALERT | ERR_FATAL;
5536 args[arg] = line;
5537 }
5538
Willy Tarreau540abe42007-05-02 20:50:16 +02005539 /* zero out remaining args and ensure that at least one entry
5540 * is zeroed out.
5541 */
5542 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 args[arg] = line;
5544 }
5545
Willy Tarreau3842f002009-06-14 11:39:52 +02005546 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005547 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005548 char *tmp;
5549
Willy Tarreau3842f002009-06-14 11:39:52 +02005550 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005551 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005552 for (arg=0; *args[arg+1]; arg++)
5553 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005554 *tmp = '\0'; // fix the next arg to \0
5555 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005556 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005557 else if (!strcmp(args[0], "default")) {
5558 kwm = KWM_DEF;
5559 for (arg=0; *args[arg+1]; arg++)
5560 args[arg] = args[arg+1]; // shift args after inversion
5561 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005562
William Lallemand0f99e342011-10-12 17:50:54 +02005563 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5564 strcmp(args[0], "log") != 0) {
5565 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005567 }
5568
Willy Tarreau977b8e42006-12-29 14:19:17 +01005569 if (!strcmp(args[0], "listen") ||
5570 !strcmp(args[0], "frontend") ||
5571 !strcmp(args[0], "backend") ||
5572 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005573 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005575 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005576 cursection = strdup(args[0]);
5577 }
5578 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005580 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005581 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005582 }
5583 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005584 confsect = CFG_USERLIST;
5585 free(cursection);
5586 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005587 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005588 else if (!strcmp(args[0], "peers")) {
5589 confsect = CFG_PEERS;
5590 free(cursection);
5591 cursection = strdup(args[0]);
5592 }
5593
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 /* else it's a section keyword */
5595
5596 switch (confsect) {
5597 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005598 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 break;
5600 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005601 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005603 case CFG_USERLIST:
5604 err_code |= cfg_parse_users(file, linenum, args, kwm);
5605 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005606 case CFG_PEERS:
5607 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5608 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005610 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005611 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005613
5614 if (err_code & ERR_ABORT)
5615 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005617 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005618 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005620 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005621}
5622
Willy Tarreaubb925012009-07-23 13:36:36 +02005623/*
5624 * Returns the error code, 0 if OK, or any combination of :
5625 * - ERR_ABORT: must abort ASAP
5626 * - ERR_FATAL: we can continue parsing but not start the service
5627 * - ERR_WARN: a warning has been emitted
5628 * - ERR_ALERT: an alert has been emitted
5629 * Only the two first ones can stop processing, the two others are just
5630 * indicators.
5631 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005632int check_config_validity()
5633{
5634 int cfgerr = 0;
5635 struct proxy *curproxy = NULL;
5636 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005637 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005638 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005639 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005640 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005642 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 /*
5644 * Now, check for the integrity of all that we have collected.
5645 */
5646
5647 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005648 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005650 /* first, we will invert the proxy list order */
5651 curproxy = NULL;
5652 while (proxy) {
5653 struct proxy *next;
5654
5655 next = proxy->next;
5656 proxy->next = curproxy;
5657 curproxy = proxy;
5658 if (!next)
5659 break;
5660 proxy = next;
5661 }
5662
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005664 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005665 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005666 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005667 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005668 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005669 unsigned int next_id;
5670
5671 if (!curproxy->uuid) {
5672 /* proxy ID not set, use automatic numbering with first
5673 * spare entry starting with next_pxid.
5674 */
5675 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5676 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5677 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005678 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005679 next_pxid++;
5680
Willy Tarreau55ea7572007-06-17 19:56:27 +02005681
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005683 /* ensure we don't keep listeners uselessly bound */
5684 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 curproxy = curproxy->next;
5686 continue;
5687 }
5688
Willy Tarreauff01a212009-03-15 13:46:16 +01005689 switch (curproxy->mode) {
5690 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005691 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005692 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005693 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5694 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005695 cfgerr++;
5696 }
5697
5698 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005699 Warning("config : servers will be ignored for %s '%s'.\n",
5700 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005701 break;
5702
5703 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005704 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005705 break;
5706
5707 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005708 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005709 break;
5710 }
5711
Willy Tarreau4348fad2012-09-20 16:48:07 +02005712 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005713 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5714 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 cfgerr++;
5716 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005717
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005718 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005719 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005720 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005721 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5722 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005723 cfgerr++;
5724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005726 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005727 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5728 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005729 cfgerr++;
5730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005732 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005733 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5734 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005735 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005736 }
5737 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005738 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005739 /* If no LB algo is set in a backend, and we're not in
5740 * transparent mode, dispatch mode nor proxy mode, we
5741 * want to use balance roundrobin by default.
5742 */
5743 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5744 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
5746 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005747
Willy Tarreau1620ec32011-08-06 17:05:02 +02005748 if (curproxy->options & PR_O_DISPATCH)
5749 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5750 else if (curproxy->options & PR_O_HTTP_PROXY)
5751 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5752 else if (curproxy->options & PR_O_TRANSP)
5753 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005754
Willy Tarreau1620ec32011-08-06 17:05:02 +02005755 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5756 if (curproxy->options & PR_O_DISABLE404) {
5757 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5758 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5759 err_code |= ERR_WARN;
5760 curproxy->options &= ~PR_O_DISABLE404;
5761 }
5762 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5763 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5764 "send-state", proxy_type_str(curproxy), curproxy->id);
5765 err_code |= ERR_WARN;
5766 curproxy->options &= ~PR_O2_CHK_SNDST;
5767 }
Willy Tarreauef781042010-01-27 11:53:01 +01005768 }
5769
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005770 /* if a default backend was specified, let's find it */
5771 if (curproxy->defbe.name) {
5772 struct proxy *target;
5773
Alex Williams96532db2009-11-01 21:27:13 -05005774 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005775 if (!target) {
5776 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5777 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005778 cfgerr++;
5779 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005780 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5781 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005782 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005783 } else {
5784 free(curproxy->defbe.name);
5785 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005786 /* we force the backend to be present on at least all of
5787 * the frontend's processes.
5788 */
5789 target->bind_proc = curproxy->bind_proc ?
5790 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005791
5792 /* Emit a warning if this proxy also has some servers */
5793 if (curproxy->srv) {
5794 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5795 curproxy->id);
5796 err_code |= ERR_WARN;
5797 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
5799 }
5800
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005801 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005802 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5803 /* map jump target for ACT_SETBE in req_rep chain */
5804 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005805 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005806 struct proxy *target;
5807
Willy Tarreaua496b602006-12-17 23:15:24 +01005808 if (exp->action != ACT_SETBE)
5809 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005810
Alex Williams96532db2009-11-01 21:27:13 -05005811 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005812 if (!target) {
5813 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5814 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005815 cfgerr++;
5816 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005817 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5818 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005819 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005820 } else {
5821 free((void *)exp->replace);
5822 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005823 /* we force the backend to be present on at least all of
5824 * the frontend's processes.
5825 */
5826 target->bind_proc = curproxy->bind_proc ?
5827 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005828 }
5829 }
5830 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005831
5832 /* find the target proxy for 'use_backend' rules */
5833 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005834 struct proxy *target;
5835
Alex Williams96532db2009-11-01 21:27:13 -05005836 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005837
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005838 if (!target) {
5839 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5840 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005841 cfgerr++;
5842 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005843 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5844 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005845 cfgerr++;
5846 } else {
5847 free((void *)rule->be.name);
5848 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005849 /* we force the backend to be present on at least all of
5850 * the frontend's processes.
5851 */
5852 target->bind_proc = curproxy->bind_proc ?
5853 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005854 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005855 }
5856
5857 /* find the target proxy for 'use_backend' rules */
5858 list_for_each_entry(srule, &curproxy->server_rules, list) {
5859 struct server *target = findserver(curproxy, srule->srv.name);
5860
5861 if (!target) {
5862 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5863 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5864 cfgerr++;
5865 continue;
5866 }
5867 free((void *)srule->srv.name);
5868 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005869 }
5870
Emeric Brunb982a3d2010-01-04 15:45:53 +01005871 /* find the target table for 'stick' rules */
5872 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5873 struct proxy *target;
5874
Emeric Brun1d33b292010-01-04 15:47:17 +01005875 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5876 if (mrule->flags & STK_IS_STORE)
5877 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5878
Emeric Brunb982a3d2010-01-04 15:45:53 +01005879 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005880 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005881 else
5882 target = curproxy;
5883
5884 if (!target) {
5885 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5886 curproxy->id, mrule->table.name);
5887 cfgerr++;
5888 }
5889 else if (target->table.size == 0) {
5890 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5891 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5892 cfgerr++;
5893 }
Willy Tarreau12785782012-04-27 21:37:17 +02005894 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5895 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005896 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5897 cfgerr++;
5898 }
5899 else {
5900 free((void *)mrule->table.name);
5901 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005902 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005903 }
5904 }
5905
5906 /* find the target table for 'store response' rules */
5907 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5908 struct proxy *target;
5909
Emeric Brun1d33b292010-01-04 15:47:17 +01005910 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5911
Emeric Brunb982a3d2010-01-04 15:45:53 +01005912 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005913 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005914 else
5915 target = curproxy;
5916
5917 if (!target) {
5918 Alert("Proxy '%s': unable to find store table '%s'.\n",
5919 curproxy->id, mrule->table.name);
5920 cfgerr++;
5921 }
5922 else if (target->table.size == 0) {
5923 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5924 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5925 cfgerr++;
5926 }
Willy Tarreau12785782012-04-27 21:37:17 +02005927 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5928 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005929 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5930 cfgerr++;
5931 }
5932 else {
5933 free((void *)mrule->table.name);
5934 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005935 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005936 }
5937 }
5938
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005939 /* find the target table for 'tcp-request' layer 4 rules */
5940 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5941 struct proxy *target;
5942
Willy Tarreau56123282010-08-06 19:06:56 +02005943 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005944 continue;
5945
5946 if (trule->act_prm.trk_ctr.table.n)
5947 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5948 else
5949 target = curproxy;
5950
5951 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005952 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5953 curproxy->id, trule->act_prm.trk_ctr.table.n,
5954 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005955 cfgerr++;
5956 }
5957 else if (target->table.size == 0) {
5958 Alert("Proxy '%s': table '%s' used but not configured.\n",
5959 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5960 cfgerr++;
5961 }
5962 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005963 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 +02005964 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5965 cfgerr++;
5966 }
5967 else {
5968 free(trule->act_prm.trk_ctr.table.n);
5969 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005970 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005971 * to pass a list of counters to track and allocate them right here using
5972 * stktable_alloc_data_type().
5973 */
5974 }
5975 }
5976
Willy Tarreaud1f96522010-08-03 19:34:32 +02005977 /* find the target table for 'tcp-request' layer 6 rules */
5978 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5979 struct proxy *target;
5980
Willy Tarreau56123282010-08-06 19:06:56 +02005981 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005982 continue;
5983
5984 if (trule->act_prm.trk_ctr.table.n)
5985 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5986 else
5987 target = curproxy;
5988
5989 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005990 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5991 curproxy->id, trule->act_prm.trk_ctr.table.n,
5992 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005993 cfgerr++;
5994 }
5995 else if (target->table.size == 0) {
5996 Alert("Proxy '%s': table '%s' used but not configured.\n",
5997 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5998 cfgerr++;
5999 }
6000 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006001 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 +02006002 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6003 cfgerr++;
6004 }
6005 else {
6006 free(trule->act_prm.trk_ctr.table.n);
6007 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006008 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006009 * to pass a list of counters to track and allocate them right here using
6010 * stktable_alloc_data_type().
6011 */
6012 }
6013 }
6014
Emeric Brun32da3c42010-09-23 18:39:19 +02006015 if (curproxy->table.peers.name) {
6016 struct peers *curpeers = peers;
6017
6018 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6019 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6020 free((void *)curproxy->table.peers.name);
6021 curproxy->table.peers.p = peers;
6022 break;
6023 }
6024 }
6025
6026 if (!curpeers) {
6027 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6028 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006029 free((void *)curproxy->table.peers.name);
6030 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006031 cfgerr++;
6032 }
6033 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006034 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6035 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006036 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006037 cfgerr++;
6038 }
6039 }
6040
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006041 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006042 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006043 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6044 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6045 "proxy", curproxy->id);
6046 cfgerr++;
6047 goto out_uri_auth_compat;
6048 }
6049
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006050 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006051 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006052 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006053 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006054
Willy Tarreau95fa4692010-02-01 13:05:50 +01006055 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6056 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006057
6058 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006059 uri_auth_compat_req[i++] = "realm";
6060 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6061 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006062
Willy Tarreau95fa4692010-02-01 13:05:50 +01006063 uri_auth_compat_req[i++] = "unless";
6064 uri_auth_compat_req[i++] = "{";
6065 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6066 uri_auth_compat_req[i++] = "}";
6067 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006068
Willy Tarreauff011f22011-01-06 17:51:27 +01006069 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6070 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006071 cfgerr++;
6072 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006073 }
6074
Willy Tarreauff011f22011-01-06 17:51:27 +01006075 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006076
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006077 if (curproxy->uri_auth->auth_realm) {
6078 free(curproxy->uri_auth->auth_realm);
6079 curproxy->uri_auth->auth_realm = NULL;
6080 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006081
6082 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006083 }
6084out_uri_auth_compat:
6085
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006086 cfgerr += acl_find_targets(curproxy);
6087
Willy Tarreau2738a142006-07-08 17:28:09 +02006088 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006089 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006090 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006091 (!curproxy->timeout.connect ||
6092 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006093 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006094 " | While not properly invalid, you will certainly encounter various problems\n"
6095 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006096 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006097 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006098 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006099 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006100
Willy Tarreau1fa31262007-12-03 00:36:16 +01006101 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6102 * We must still support older configurations, so let's find out whether those
6103 * parameters have been set or must be copied from contimeouts.
6104 */
6105 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006106 if (!curproxy->timeout.tarpit ||
6107 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006108 /* tarpit timeout not set. We search in the following order:
6109 * default.tarpit, curr.connect, default.connect.
6110 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006111 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006112 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006113 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006114 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006115 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006116 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006117 }
6118 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006119 (!curproxy->timeout.queue ||
6120 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006121 /* queue timeout not set. We search in the following order:
6122 * default.queue, curr.connect, default.connect.
6123 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006124 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006125 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006126 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006127 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006128 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006129 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006130 }
6131 }
6132
Willy Tarreau1620ec32011-08-06 17:05:02 +02006133 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006134 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6135 curproxy->check_req = (char *)malloc(curproxy->check_len);
6136 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006137 }
6138
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006139 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006140 if (curproxy->nb_req_cap) {
6141 if (curproxy->mode == PR_MODE_HTTP) {
6142 curproxy->req_cap_pool = create_pool("ptrcap",
6143 curproxy->nb_req_cap * sizeof(char *),
6144 MEM_F_SHARED);
6145 } else {
6146 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6147 proxy_type_str(curproxy), curproxy->id);
6148 err_code |= ERR_WARN;
6149 curproxy->to_log &= ~LW_REQHDR;
6150 curproxy->nb_req_cap = 0;
6151 }
6152 }
6153
6154 if (curproxy->nb_rsp_cap) {
6155 if (curproxy->mode == PR_MODE_HTTP) {
6156 curproxy->rsp_cap_pool = create_pool("ptrcap",
6157 curproxy->nb_rsp_cap * sizeof(char *),
6158 MEM_F_SHARED);
6159 } else {
6160 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6161 proxy_type_str(curproxy), curproxy->id);
6162 err_code |= ERR_WARN;
6163 curproxy->to_log &= ~LW_REQHDR;
6164 curproxy->nb_rsp_cap = 0;
6165 }
6166 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006167
Willy Tarreau196729e2012-05-31 19:30:26 +02006168 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006169 if (!(curproxy->cap & PR_CAP_FE)) {
6170 if (curproxy->logformat_string != default_http_log_format &&
6171 curproxy->logformat_string != default_tcp_log_format &&
6172 curproxy->logformat_string != clf_http_log_format)
6173 free(curproxy->logformat_string);
6174 curproxy->logformat_string = NULL;
6175 }
6176
Willy Tarreau196729e2012-05-31 19:30:26 +02006177 if (curproxy->logformat_string)
6178 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6179
6180 if (curproxy->uniqueid_format_string)
6181 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6182
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 /* first, we will invert the servers list order */
6184 newsrv = NULL;
6185 while (curproxy->srv) {
6186 struct server *next;
6187
6188 next = curproxy->srv->next;
6189 curproxy->srv->next = newsrv;
6190 newsrv = curproxy->srv;
6191 if (!next)
6192 break;
6193 curproxy->srv = next;
6194 }
6195
Willy Tarreaudd701652010-05-25 23:03:02 +02006196 /* assign automatic UIDs to servers which don't have one yet */
6197 next_id = 1;
6198 newsrv = curproxy->srv;
6199 while (newsrv != NULL) {
6200 if (!newsrv->puid) {
6201 /* server ID not set, use automatic numbering with first
6202 * spare entry starting with next_svid.
6203 */
6204 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6205 newsrv->conf.id.key = newsrv->puid = next_id;
6206 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6207 }
6208 next_id++;
6209 newsrv = newsrv->next;
6210 }
6211
Willy Tarreau20697042007-11-15 23:26:18 +01006212 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006213 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214
Willy Tarreau62c3be22012-01-20 13:12:32 +01006215 /*
6216 * If this server supports a maxconn parameter, it needs a dedicated
6217 * tasks to fill the emptied slots when a connection leaves.
6218 * Also, resolve deferred tracking dependency if needed.
6219 */
6220 newsrv = curproxy->srv;
6221 while (newsrv != NULL) {
6222 if (newsrv->minconn > newsrv->maxconn) {
6223 /* Only 'minconn' was specified, or it was higher than or equal
6224 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6225 * this will avoid further useless expensive computations.
6226 */
6227 newsrv->maxconn = newsrv->minconn;
6228 } else if (newsrv->maxconn && !newsrv->minconn) {
6229 /* minconn was not specified, so we set it to maxconn */
6230 newsrv->minconn = newsrv->maxconn;
6231 }
6232
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006233#ifdef USE_OPENSSL
6234#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6235#define SSL_OP_NO_COMPRESSION 0
6236#endif
6237#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6238#define SSL_MODE_RELEASE_BUFFERS 0
6239#endif
6240#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6241#define SSL_OP_NO_COMPRESSION 0
6242#endif
6243 if (newsrv->use_ssl) {
6244 int ssloptions =
6245 SSL_OP_ALL | /* all known workarounds for bugs */
6246 SSL_OP_NO_SSLv2 |
6247 SSL_OP_NO_COMPRESSION;
6248 int sslmode =
6249 SSL_MODE_ENABLE_PARTIAL_WRITE |
6250 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6251 SSL_MODE_RELEASE_BUFFERS;
6252
6253 /* Initiate SSL context for current server */
6254 newsrv->ssl_ctx.reused_sess = NULL;
6255 newsrv->data = &ssl_sock;
6256 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6257 if(!newsrv->ssl_ctx.ctx) {
6258
6259 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6260 proxy_type_str(curproxy), curproxy->id,
6261 newsrv->id);
6262 cfgerr++;
6263 goto next_srv;
6264 }
6265
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006266 if (newsrv->ssl_ctx.nosslv3)
6267 ssloptions |= SSL_OP_NO_SSLv3;
6268 if (newsrv->ssl_ctx.notlsv1)
6269 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006270 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6271 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6272 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6273 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006274 if (newsrv->ssl_ctx.ciphers &&
6275 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6276 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6277 curproxy->id, newsrv->id,
6278 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6279 cfgerr++;
6280 goto next_srv;
6281 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006282 }
6283#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006284 if (newsrv->trackit) {
6285 struct proxy *px;
6286 struct server *srv;
6287 char *pname, *sname;
6288
6289 pname = newsrv->trackit;
6290 sname = strrchr(pname, '/');
6291
6292 if (sname)
6293 *sname++ = '\0';
6294 else {
6295 sname = pname;
6296 pname = NULL;
6297 }
6298
6299 if (pname) {
6300 px = findproxy(pname, PR_CAP_BE);
6301 if (!px) {
6302 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6303 proxy_type_str(curproxy), curproxy->id,
6304 newsrv->id, pname);
6305 cfgerr++;
6306 goto next_srv;
6307 }
6308 } else
6309 px = curproxy;
6310
6311 srv = findserver(px, sname);
6312 if (!srv) {
6313 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6314 proxy_type_str(curproxy), curproxy->id,
6315 newsrv->id, sname);
6316 cfgerr++;
6317 goto next_srv;
6318 }
6319
6320 if (!(srv->state & SRV_CHECKED)) {
6321 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6322 "tracking as it does not have checks enabled.\n",
6323 proxy_type_str(curproxy), curproxy->id,
6324 newsrv->id, px->id, srv->id);
6325 cfgerr++;
6326 goto next_srv;
6327 }
6328
6329 if (curproxy != px &&
6330 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6331 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6332 "tracking: disable-on-404 option inconsistency.\n",
6333 proxy_type_str(curproxy), curproxy->id,
6334 newsrv->id, px->id, srv->id);
6335 cfgerr++;
6336 goto next_srv;
6337 }
6338
6339 /* if the other server is forced disabled, we have to do the same here */
6340 if (srv->state & SRV_MAINTAIN) {
6341 newsrv->state |= SRV_MAINTAIN;
6342 newsrv->state &= ~SRV_RUNNING;
6343 newsrv->health = 0;
6344 }
6345
6346 newsrv->track = srv;
6347 newsrv->tracknext = srv->tracknext;
6348 srv->tracknext = newsrv;
6349
6350 free(newsrv->trackit);
6351 newsrv->trackit = NULL;
6352 }
6353 next_srv:
6354 newsrv = newsrv->next;
6355 }
6356
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006357 /* We have to initialize the server lookup mechanism depending
6358 * on what LB algorithm was choosen.
6359 */
6360
6361 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6362 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6363 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006364 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6365 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6366 init_server_map(curproxy);
6367 } else {
6368 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6369 fwrr_init_server_groups(curproxy);
6370 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006371 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006372
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006373 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006374 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6375 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6376 fwlc_init_server_tree(curproxy);
6377 } else {
6378 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6379 fas_init_server_tree(curproxy);
6380 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006381 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006382
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006383 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006384 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6385 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6386 chash_init_server_tree(curproxy);
6387 } else {
6388 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6389 init_server_map(curproxy);
6390 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006391 break;
6392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393
6394 if (curproxy->options & PR_O_LOGASAP)
6395 curproxy->to_log &= ~LW_BYTES;
6396
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006397 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006398 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006399 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6400 proxy_type_str(curproxy), curproxy->id);
6401 err_code |= ERR_WARN;
6402 }
6403
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006404 if (curproxy->mode != PR_MODE_HTTP) {
6405 int optnum;
6406
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006407 if (curproxy->uri_auth) {
6408 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6409 proxy_type_str(curproxy), curproxy->id);
6410 err_code |= ERR_WARN;
6411 curproxy->uri_auth = NULL;
6412 }
6413
Willy Tarreau87cf5142011-08-19 22:57:24 +02006414 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006415 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6416 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6417 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006418 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006419 }
6420
6421 if (curproxy->options & PR_O_ORGTO) {
6422 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6423 "originalto", proxy_type_str(curproxy), curproxy->id);
6424 err_code |= ERR_WARN;
6425 curproxy->options &= ~PR_O_ORGTO;
6426 }
6427
6428 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6429 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6430 (curproxy->cap & cfg_opts[optnum].cap) &&
6431 (curproxy->options & cfg_opts[optnum].val)) {
6432 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6433 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6434 err_code |= ERR_WARN;
6435 curproxy->options &= ~cfg_opts[optnum].val;
6436 }
6437 }
6438
6439 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6440 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6441 (curproxy->cap & cfg_opts2[optnum].cap) &&
6442 (curproxy->options2 & cfg_opts2[optnum].val)) {
6443 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6444 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6445 err_code |= ERR_WARN;
6446 curproxy->options2 &= ~cfg_opts2[optnum].val;
6447 }
6448 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006449
Willy Tarreauefa5f512010-03-30 20:13:29 +02006450#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006451 if (curproxy->bind_hdr_occ) {
6452 curproxy->bind_hdr_occ = 0;
6453 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6454 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6455 err_code |= ERR_WARN;
6456 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006457#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006458 }
6459
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006461 * ensure that we're not cross-dressing a TCP server into HTTP.
6462 */
6463 newsrv = curproxy->srv;
6464 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006465 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006466 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6467 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006468 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006469 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006470
Willy Tarreau0cec3312011-10-31 13:49:26 +01006471 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6472 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6473 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6474 err_code |= ERR_WARN;
6475 }
6476
Willy Tarreauefa5f512010-03-30 20:13:29 +02006477#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006478 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6479 newsrv->bind_hdr_occ = 0;
6480 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6481 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6482 err_code |= ERR_WARN;
6483 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006484#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006485 newsrv = newsrv->next;
6486 }
6487
Willy Tarreauc1a21672009-08-16 22:37:44 +02006488 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006489 curproxy->accept = frontend_accept;
6490
Willy Tarreauc1a21672009-08-16 22:37:44 +02006491 if (curproxy->tcp_req.inspect_delay ||
6492 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006493 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006494
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006495 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006496 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006497 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006498 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006499
6500 /* both TCP and HTTP must check switching rules */
6501 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6502 }
6503
6504 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006505 if (curproxy->tcp_req.inspect_delay ||
6506 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6507 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6508
Emeric Brun97679e72010-09-23 17:56:44 +02006509 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6510 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6511
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006512 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006513 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006514 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006515 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006516
6517 /* If the backend does requires RDP cookie persistence, we have to
6518 * enable the corresponding analyser.
6519 */
6520 if (curproxy->options2 & PR_O2_RDPC_PRST)
6521 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6522 }
6523
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006524 /* Configure SSL for each bind line.
6525 * Note: if configuration fails at some point, the ->ctx member
6526 * remains NULL so that listeners can later detach.
6527 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006528 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6529 if (!bind_conf->is_ssl)
6530 continue;
6531#ifdef USE_OPENSSL
6532 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006533 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006534 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006535 cfgerr++;
6536 continue;
6537 }
6538
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006539 if (shared_context_init(global.tune.sslcachesize) < 0) {
6540 Alert("Unable to allocate SSL session cache.\n");
6541 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006542 continue;
6543 }
6544
Emeric Brunfc0421f2012-09-07 17:30:07 +02006545 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006546 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006547#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006548 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006549
Willy Tarreaue6b98942007-10-29 01:09:36 +01006550 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006551 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006552 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006553 if (!listener->luid) {
6554 /* listener ID not set, use automatic numbering with first
6555 * spare entry starting with next_luid.
6556 */
6557 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6558 listener->conf.id.key = listener->luid = next_id;
6559 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006560 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006561 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006562
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006563 /* enable separate counters */
6564 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6565 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6566 if (!listener->name) {
6567 sprintf(trash, "sock-%d", listener->luid);
6568 listener->name = strdup(trash);
6569 }
6570 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006571
Willy Tarreaue6b98942007-10-29 01:09:36 +01006572 if (curproxy->options & PR_O_TCP_NOLING)
6573 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006574 if (!listener->maxconn)
6575 listener->maxconn = curproxy->maxconn;
6576 if (!listener->backlog)
6577 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006578 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006579 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006580 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006581 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006582
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006583 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6584 listener->options |= LI_O_TCP_RULES;
6585
Willy Tarreaude3041d2010-05-31 10:56:17 +02006586 if (curproxy->mon_mask.s_addr)
6587 listener->options |= LI_O_CHK_MONNET;
6588
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006589 /* smart accept mode is automatic in HTTP mode */
6590 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006591 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006592 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6593 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006594 }
6595
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006596 /* Release unused SSL configs */
6597 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6598 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006599 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006600#ifdef USE_OPENSSL
6601 ssl_sock_free_all_ctx(bind_conf);
6602 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006603 free(bind_conf->ecdhe);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006604#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006605 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006606
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006607 /* Check multi-process mode compatibility for the current proxy */
6608 if (global.nbproc > 1) {
6609 int nbproc = 0;
6610 if (curproxy->bind_proc) {
6611 int proc;
6612 for (proc = 0; proc < global.nbproc; proc++) {
6613 if (curproxy->bind_proc & (1 << proc)) {
6614 nbproc++;
6615 }
6616 }
6617 } else {
6618 nbproc = global.nbproc;
6619 }
6620 if (curproxy->table.peers.name) {
6621 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6622 curproxy->id);
6623 cfgerr++;
6624 }
6625 if (nbproc > 1) {
6626 if (curproxy->uri_auth) {
6627 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6628 curproxy->id);
6629 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6630 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6631 curproxy->id);
6632 }
6633 }
6634 if (curproxy->appsession_name) {
6635 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6636 curproxy->id);
6637 }
6638 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6639 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6640 curproxy->id);
6641 }
6642 }
6643 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006644
6645 /* create the task associated with the proxy */
6646 curproxy->task = task_new();
6647 if (curproxy->task) {
6648 curproxy->task->context = curproxy;
6649 curproxy->task->process = manage_proxy;
6650 /* no need to queue, it will be done automatically if some
6651 * listener gets limited.
6652 */
6653 curproxy->task->expire = TICK_ETERNITY;
6654 } else {
6655 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6656 curproxy->id);
6657 cfgerr++;
6658 }
6659
Willy Tarreaubaaee002006-06-26 02:48:02 +02006660 curproxy = curproxy->next;
6661 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006662
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006663 /* Check multi-process mode compatibility */
6664 if (global.nbproc > 1) {
6665 if (global.stats_fe) {
6666 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6667 }
6668 }
6669
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006670 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6671 struct auth_users *curuser;
6672 int g;
6673
6674 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6675 unsigned int group_mask = 0;
6676 char *group = NULL;
6677
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006678 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006679 continue;
6680
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006681 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006682
6683 for (g = 0; g < curuserlist->grpcnt; g++)
6684 if (!strcmp(curuserlist->groups[g], group))
6685 break;
6686
6687 if (g == curuserlist->grpcnt) {
6688 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6689 curuserlist->name, group, curuser->user);
6690 err_code |= ERR_ALERT | ERR_FATAL;
6691 goto out;
6692 }
6693
6694 group_mask |= (1 << g);
6695 }
6696
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006697 free(curuser->u.groups);
6698 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006699 }
6700
6701 for (g = 0; g < curuserlist->grpcnt; g++) {
6702 char *user = NULL;
6703
6704 if (!curuserlist->groupusers[g])
6705 continue;
6706
6707 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6708 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6709 if (!strcmp(curuser->user, user))
6710 break;
6711
6712 if (!curuser) {
6713 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6714 curuserlist->name, user, curuserlist->groups[g]);
6715 err_code |= ERR_ALERT | ERR_FATAL;
6716 goto out;
6717 }
6718
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006719 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006720 }
6721
6722 free(curuserlist->groupusers[g]);
6723 }
6724
6725 free(curuserlist->groupusers);
6726
6727#ifdef DEBUG_AUTH
6728 for (g = 0; g < curuserlist->grpcnt; g++) {
6729 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6730
6731 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006732 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006733 fprintf(stderr, " %s", curuser->user);
6734 }
6735
6736 fprintf(stderr, "\n");
6737 }
6738#endif
6739
Willy Tarreaufbb78422011-06-05 15:38:35 +02006740 }
6741
6742 /* automatically compute fullconn if not set. We must not do it in the
6743 * loop above because cross-references are not yet fully resolved.
6744 */
6745 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6746 /* If <fullconn> is not set, let's set it to 10% of the sum of
6747 * the possible incoming frontend's maxconns.
6748 */
6749 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6750 struct proxy *fe;
6751 int total = 0;
6752
6753 /* sum up the number of maxconns of frontends which
6754 * reference this backend at least once or which are
6755 * the same one ('listen').
6756 */
6757 for (fe = proxy; fe; fe = fe->next) {
6758 struct switching_rule *rule;
6759 struct hdr_exp *exp;
6760 int found = 0;
6761
6762 if (!(fe->cap & PR_CAP_FE))
6763 continue;
6764
6765 if (fe == curproxy) /* we're on a "listen" instance */
6766 found = 1;
6767
6768 if (fe->defbe.be == curproxy) /* "default_backend" */
6769 found = 1;
6770
6771 /* check if a "use_backend" rule matches */
6772 if (!found) {
6773 list_for_each_entry(rule, &fe->switching_rules, list) {
6774 if (rule->be.backend == curproxy) {
6775 found = 1;
6776 break;
6777 }
6778 }
6779 }
6780
6781 /* check if a "reqsetbe" rule matches */
6782 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6783 if (exp->action == ACT_SETBE &&
6784 (struct proxy *)exp->replace == curproxy) {
6785 found = 1;
6786 break;
6787 }
6788 }
6789
6790 /* now we've checked all possible ways to reference a backend
6791 * from a frontend.
6792 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006793 if (!found)
6794 continue;
6795 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006796 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006797 /* we have the sum of the maxconns in <total>. We only
6798 * keep 10% of that sum to set the default fullconn, with
6799 * a hard minimum of 1 (to avoid a divide by zero).
6800 */
6801 curproxy->fullconn = (total + 9) / 10;
6802 if (!curproxy->fullconn)
6803 curproxy->fullconn = 1;
6804 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006805 }
6806
Willy Tarreau056f5682010-06-06 15:51:11 +02006807 /* initialize stick-tables on backend capable proxies. This must not
6808 * be done earlier because the data size may be discovered while parsing
6809 * other proxies.
6810 */
6811 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006812 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006813
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006814 /*
6815 * Recount currently required checks.
6816 */
6817
6818 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6819 int optnum;
6820
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006821 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6822 if (curproxy->options & cfg_opts[optnum].val)
6823 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006824
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006825 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6826 if (curproxy->options2 & cfg_opts2[optnum].val)
6827 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006828 }
6829
Willy Tarreau122541c2011-09-07 21:24:49 +02006830 if (peers) {
6831 struct peers *curpeers = peers, **last;
6832 struct peer *p, *pb;
6833
6834 /* Remove all peers sections which don't have a valid listener.
6835 * This can happen when a peers section is never referenced and
6836 * does not contain a local peer.
6837 */
6838 last = &peers;
6839 while (*last) {
6840 curpeers = *last;
6841 if (curpeers->peers_fe) {
6842 last = &curpeers->next;
6843 continue;
6844 }
6845
6846 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6847 curpeers->id, localpeer);
6848
6849 p = curpeers->remote;
6850 while (p) {
6851 pb = p->next;
6852 free(p->id);
6853 free(p);
6854 p = pb;
6855 }
6856
6857 /* Destroy and unlink this curpeers section.
6858 * Note: curpeers is backed up into *last.
6859 */
6860 free(curpeers->id);
6861 curpeers = curpeers->next;
6862 free(*last);
6863 *last = curpeers;
6864 }
6865 }
6866
Willy Tarreauac1932d2011-10-24 19:14:41 +02006867 if (!global.tune.max_http_hdr)
6868 global.tune.max_http_hdr = MAX_HTTP_HDR;
6869
Willy Tarreau34eb6712011-10-24 18:15:04 +02006870 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006871 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006872 MEM_F_SHARED);
6873
Willy Tarreaubb925012009-07-23 13:36:36 +02006874 if (cfgerr > 0)
6875 err_code |= ERR_ALERT | ERR_FATAL;
6876 out:
6877 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878}
6879
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006880/*
6881 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6882 * parsing sessions.
6883 */
6884void cfg_register_keywords(struct cfg_kw_list *kwl)
6885{
6886 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6887}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006888
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006889/*
6890 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6891 */
6892void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6893{
6894 LIST_DEL(&kwl->list);
6895 LIST_INIT(&kwl->list);
6896}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897
6898/*
6899 * Local variables:
6900 * c-indent-level: 8
6901 * c-basic-offset: 8
6902 * End:
6903 */