blob: e33ab6129abe9ec3a2dc038f2901f3a712cb196d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
Willy Tarreau3a269182013-03-04 19:53:29 +0100220 int prefix_path_len = (curproxy != global.stats_fe && global.unix_bind.prefix) ? strlen(global.unix_bind.prefix) : 0;
Emeric Bruned760922010-10-22 17:59:25 +0200221 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreaud393a622013-03-04 18:22:00 +0100242 ss2 = str2sa_range(str, &port, &end, NULL, NULL);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100253 if (!port || !end) {
254 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
255 goto fail;
256 }
257
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100258 /* OK the address looks correct */
259 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260
Emeric Bruned760922010-10-22 17:59:25 +0200261 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
265
266 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200267 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200268 goto fail;
269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 }
271
272 for (; port <= end; port++) {
273 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100274 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200275 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
276 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
277 l->frontend = curproxy;
278 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279
280 l->fd = -1;
281 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200282 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100283 l->state = LI_INIT;
284
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100285 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100287 tcpv4_add_listener(l);
288 }
Emeric Bruned760922010-10-22 17:59:25 +0200289 else if (ss.ss_family == AF_INET6) {
290 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
291 tcpv6_add_listener(l);
292 }
293 else {
Emeric Bruned760922010-10-22 17:59:25 +0200294 uxst_add_listener(l);
295 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200297 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100298 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 } /* end for(port) */
300 } /* end while(next) */
301 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200302 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 fail:
304 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200305 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306}
307
Willy Tarreau977b8e42006-12-29 14:19:17 +0100308/*
309 * Sends a warning if proxy <proxy> does not have at least one of the
310 * capabilities in <cap>. An optionnal <hint> may be added at the end
311 * of the warning to help the user. Returns 1 if a warning was emitted
312 * or 0 if the condition is valid.
313 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100314int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100315{
316 char *msg;
317
318 switch (cap) {
319 case PR_CAP_BE: msg = "no backend"; break;
320 case PR_CAP_FE: msg = "no frontend"; break;
321 case PR_CAP_RS: msg = "no ruleset"; break;
322 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
323 default: msg = "not enough"; break;
324 }
325
326 if (!(proxy->cap & cap)) {
327 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100328 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100329 return 1;
330 }
331 return 0;
332}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
339 if (!LIST_ISEMPTY(&proxy->block_cond)) {
340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
347/* Report a warning if a rule is placed after a reqrewrite rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100350int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200351{
352 if (proxy->req_exp) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
360/* Report a warning if a rule is placed after a reqadd rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100365 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a redirect rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
378 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a 'use_backend' rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
403 warnif_rule_after_reqadd(proxy, file, line, arg) ||
404 warnif_rule_after_redirect(proxy, file, line, arg) ||
405 warnif_rule_after_use_backend(proxy, file, line, arg);
406}
407
408/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100409int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200410{
411 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
412 warnif_rule_after_redirect(proxy, file, line, arg) ||
413 warnif_rule_after_use_backend(proxy, file, line, arg);
414}
415
416/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100417int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200418{
419 return warnif_rule_after_redirect(proxy, file, line, arg) ||
420 warnif_rule_after_use_backend(proxy, file, line, arg);
421}
422
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423/* Report it if a request ACL condition uses some response-only parameters. It
424 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
425 * Note that <cond> may be NULL and then will be ignored.
426 */
427static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
428{
429 struct acl *acl;
430
431 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
432 return 0;
433
434 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
435 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
436 file, line, acl ? acl->name : "(unknown)");
437 return ERR_WARN;
438}
439
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100440/* Report it if a request ACL condition uses some request-only volatile parameters.
441 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
442 * Note that <cond> may be NULL and then will be ignored.
443 */
444static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
445{
446 struct acl *acl;
447
448 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
449 return 0;
450
451 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
452 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
453 file, line, acl ? acl->name : "(unknown)");
454 return ERR_WARN;
455}
456
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100457
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 * parse a line in a <global> section. Returns the error code, 0 if OK, or
460 * any combination of :
461 * - ERR_ABORT: must abort ASAP
462 * - ERR_FATAL: we can continue parsing but not start the service
463 * - ERR_WARN: a warning has been emitted
464 * - ERR_ALERT: an alert has been emitted
465 * Only the two first ones can stop processing, the two others are just
466 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200468int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469{
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200471 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200472
473 if (!strcmp(args[0], "global")) { /* new section */
474 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200477 else if (!strcmp(args[0], "ca-base")) {
478#ifdef USE_OPENSSL
479 if (global.ca_base != NULL) {
480 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT;
482 goto out;
483 }
484 if (*(args[1]) == 0) {
485 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488 }
489 global.ca_base = strdup(args[1]);
490#else
491 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
494#endif
495 }
496 else if (!strcmp(args[0], "crt-base")) {
497#ifdef USE_OPENSSL
498 if (global.crt_base != NULL) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT;
501 goto out;
502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
507 }
508 global.crt_base = strdup(args[1]);
509#else
510 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
511 err_code |= ERR_ALERT | ERR_FATAL;
512 goto out;
513#endif
514 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200515 else if (!strcmp(args[0], "daemon")) {
516 global.mode |= MODE_DAEMON;
517 }
518 else if (!strcmp(args[0], "debug")) {
519 global.mode |= MODE_DEBUG;
520 }
521 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100522 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200524 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100525 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200527 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100528 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100530 else if (!strcmp(args[0], "nosplice")) {
531 global.tune.options &= ~GTUNE_USE_SPLICE;
532 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200533 else if (!strcmp(args[0], "quiet")) {
534 global.mode |= MODE_QUIET;
535 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 else if (!strcmp(args[0], "tune.maxpollevents")) {
537 if (global.tune.maxpollevents != 0) {
538 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 if (*(args[1]) == 0) {
543 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200544 err_code |= ERR_ALERT | ERR_FATAL;
545 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200546 }
547 global.tune.maxpollevents = atol(args[1]);
548 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 else if (!strcmp(args[0], "tune.maxaccept")) {
550 if (global.tune.maxaccept != 0) {
551 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 if (*(args[1]) == 0) {
556 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200557 err_code |= ERR_ALERT | ERR_FATAL;
558 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100559 }
560 global.tune.maxaccept = atol(args[1]);
561 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200562 else if (!strcmp(args[0], "tune.chksize")) {
563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.chksize = atol(args[1]);
569 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200570#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100571 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.sslcachesize = atol(args[1]);
578 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100579 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
580 unsigned int ssllifetime;
581 const char *res;
582
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588
589 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
590 if (res) {
591 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
592 file, linenum, *res, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596
597 global.tune.ssllifetime = ssllifetime;
598 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100599 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.ssl_max_record = atol(args[1]);
606 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200607#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200608 else if (!strcmp(args[0], "tune.bufsize")) {
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
613 }
614 global.tune.bufsize = atol(args[1]);
615 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
616 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100617 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200618 }
619 else if (!strcmp(args[0], "tune.maxrewrite")) {
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.tune.maxrewrite = atol(args[1]);
626 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
627 global.tune.maxrewrite = global.tune.bufsize / 2;
628 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100629 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
630 if (global.tune.client_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.client_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
643 if (global.tune.server_rcvbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.server_rcvbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.client")) {
656 if (global.tune.client_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.client_sndbuf = atol(args[1]);
667 }
668 else if (!strcmp(args[0], "tune.sndbuf.server")) {
669 if (global.tune.server_sndbuf != 0) {
670 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT;
672 goto out;
673 }
674 if (*(args[1]) == 0) {
675 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.server_sndbuf = atol(args[1]);
680 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200681 else if (!strcmp(args[0], "tune.pipesize")) {
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
686 }
687 global.tune.pipesize = atol(args[1]);
688 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100689 else if (!strcmp(args[0], "tune.http.cookielen")) {
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.cookie_len = atol(args[1]) + 1;
696 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200697 else if (!strcmp(args[0], "tune.http.maxhdr")) {
698 if (*(args[1]) == 0) {
699 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703 global.tune.max_http_hdr = atol(args[1]);
704 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100705 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
706#ifdef USE_ZLIB
707 if (*args[1]) {
708 global.tune.zlibmemlevel = atoi(args[1]);
709 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 } else {
716 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
717 file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721#else
722 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
725#endif
726 }
727 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
728#ifdef USE_ZLIB
729 if (*args[1]) {
730 global.tune.zlibwindowsize = atoi(args[1]);
731 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737 } else {
738 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
739 file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743#else
744 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747#endif
748 }
William Lallemandf3747832012-11-09 12:33:10 +0100749 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
750 if (*args[1]) {
751 global.tune.comp_maxlevel = atoi(args[1]);
752 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
753 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
754 file, linenum, args[0]);
755 err_code |= ERR_ALERT | ERR_FATAL;
756 goto out;
757 }
758 } else {
759 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
760 file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200765 else if (!strcmp(args[0], "uid")) {
766 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200767 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200768 err_code |= ERR_ALERT;
769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 }
771 if (*(args[1]) == 0) {
772 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT | ERR_FATAL;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 global.uid = atol(args[1]);
777 }
778 else if (!strcmp(args[0], "gid")) {
779 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200780 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT;
782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200783 }
784 if (*(args[1]) == 0) {
785 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200788 }
789 global.gid = atol(args[1]);
790 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200791 /* user/group name handling */
792 else if (!strcmp(args[0], "user")) {
793 struct passwd *ha_user;
794 if (global.uid != 0) {
795 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT;
797 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200798 }
799 errno = 0;
800 ha_user = getpwnam(args[1]);
801 if (ha_user != NULL) {
802 global.uid = (int)ha_user->pw_uid;
803 }
804 else {
805 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 +0200806 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200807 }
808 }
809 else if (!strcmp(args[0], "group")) {
810 struct group *ha_group;
811 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200812 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200815 }
816 errno = 0;
817 ha_group = getgrnam(args[1]);
818 if (ha_group != NULL) {
819 global.gid = (int)ha_group->gr_gid;
820 }
821 else {
822 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 +0200823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200824 }
825 }
826 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 if (*(args[1]) == 0) {
829 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 global.nbproc = atol(args[1]);
834 }
835 else if (!strcmp(args[0], "maxconn")) {
836 if (global.maxconn != 0) {
837 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200838 err_code |= ERR_ALERT;
839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 }
841 if (*(args[1]) == 0) {
842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 }
846 global.maxconn = atol(args[1]);
847#ifdef SYSTEM_MAXCONN
848 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
849 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);
850 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200851 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 }
853#endif /* SYSTEM_MAXCONN */
854 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200855 else if (!strcmp(args[0], "maxsslconn")) {
856#ifdef USE_OPENSSL
857 if (*(args[1]) == 0) {
858 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 global.maxsslconn = atol(args[1]);
863#else
Emeric Brun0914df82012-10-02 18:45:42 +0200864 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200867#endif
868 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200869 else if (!strcmp(args[0], "maxconnrate")) {
870 if (global.cps_lim != 0) {
871 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT;
873 goto out;
874 }
875 if (*(args[1]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 global.cps_lim = atol(args[1]);
881 }
William Lallemandd85f9172012-11-09 17:05:39 +0100882 else if (!strcmp(args[0], "maxcomprate")) {
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.comp_rate_lim = atoi(args[1]) * 1024;
889 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100890 else if (!strcmp(args[0], "maxpipes")) {
891 if (global.maxpipes != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200893 err_code |= ERR_ALERT;
894 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100895 }
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100900 }
901 global.maxpipes = atol(args[1]);
902 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100903 else if (!strcmp(args[0], "maxzlibmem")) {
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
William Lallemande3a7d992012-11-20 11:25:20 +0100909 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100910 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100911 else if (!strcmp(args[0], "maxcompcpuusage")) {
912 if (*(args[1]) == 0) {
913 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100918 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100919 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
922 }
923}
924
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 else if (!strcmp(args[0], "ulimit-n")) {
926 if (global.rlimit_nofile != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.rlimit_nofile = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "chroot")) {
939 if (global.chroot != NULL) {
940 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200941 err_code |= ERR_ALERT;
942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 if (*(args[1]) == 0) {
945 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
947 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949 global.chroot = strdup(args[1]);
950 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200951 else if (!strcmp(args[0], "description")) {
952 int i, len=0;
953 char *d;
954
955 if (!*args[1]) {
956 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
957 file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961
962 for(i=1; *args[i]; i++)
963 len += strlen(args[i])+1;
964
965 if (global.desc)
966 free(global.desc);
967
968 global.desc = d = (char *)calloc(1, len);
969
970 d += sprintf(d, "%s", args[1]);
971 for(i=2; *args[i]; i++)
972 d += sprintf(d, " %s", args[i]);
973 }
974 else if (!strcmp(args[0], "node")) {
975 int i;
976 char c;
977
978 for (i=0; args[1][i]; i++) {
979 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100980 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
981 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200982 break;
983 }
984
985 if (!i || args[1][i]) {
986 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
987 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
988 file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992
993 if (global.node)
994 free(global.node);
995
996 global.node = strdup(args[1]);
997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 else if (!strcmp(args[0], "pidfile")) {
999 if (global.pidfile != NULL) {
1000 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001001 err_code |= ERR_ALERT;
1002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001003 }
1004 if (*(args[1]) == 0) {
1005 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 }
1009 global.pidfile = strdup(args[1]);
1010 }
Emeric Bruned760922010-10-22 17:59:25 +02001011 else if (!strcmp(args[0], "unix-bind")) {
1012 int cur_arg = 1;
1013 while (*(args[cur_arg])) {
1014 if (!strcmp(args[cur_arg], "prefix")) {
1015 if (global.unix_bind.prefix != NULL) {
1016 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1017 err_code |= ERR_ALERT;
1018 cur_arg += 2;
1019 continue;
1020 }
1021
1022 if (*(args[cur_arg+1]) == 0) {
1023 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1028 cur_arg += 2;
1029 continue;
1030 }
1031
1032 if (!strcmp(args[cur_arg], "mode")) {
1033
1034 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1035 cur_arg += 2;
1036 continue;
1037 }
1038
1039 if (!strcmp(args[cur_arg], "uid")) {
1040
1041 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1042 cur_arg += 2;
1043 continue;
1044 }
1045
1046 if (!strcmp(args[cur_arg], "gid")) {
1047
1048 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1049 cur_arg += 2;
1050 continue;
1051 }
1052
1053 if (!strcmp(args[cur_arg], "user")) {
1054 struct passwd *user;
1055
1056 user = getpwnam(args[cur_arg + 1]);
1057 if (!user) {
1058 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1059 file, linenum, args[0], args[cur_arg + 1 ]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063
1064 global.unix_bind.ux.uid = user->pw_uid;
1065 cur_arg += 2;
1066 continue;
1067 }
1068
1069 if (!strcmp(args[cur_arg], "group")) {
1070 struct group *group;
1071
1072 group = getgrnam(args[cur_arg + 1]);
1073 if (!group) {
1074 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1075 file, linenum, args[0], args[cur_arg + 1 ]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079
1080 global.unix_bind.ux.gid = group->gr_gid;
1081 cur_arg += 2;
1082 continue;
1083 }
1084
Willy Tarreaub48f9582011-09-05 01:17:06 +02001085 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001086 file, linenum, args[0]);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto out;
1089 }
1090 }
William Lallemand0f99e342011-10-12 17:50:54 +02001091 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1092 /* delete previous herited or defined syslog servers */
1093 struct logsrv *back;
1094 struct logsrv *tmp;
1095
1096 if (*(args[1]) != 0) {
1097 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
1100 }
1101
1102 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1103 LIST_DEL(&tmp->list);
1104 free(tmp);
1105 }
1106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001108 struct logsrv *logsrv;
1109
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 if (*(args[1]) == 0 || *(args[2]) == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001114 }
William Lallemand0f99e342011-10-12 17:50:54 +02001115
1116 logsrv = calloc(1, sizeof(struct logsrv));
1117
1118 logsrv->facility = get_log_facility(args[2]);
1119 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001122 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 }
1124
William Lallemand0f99e342011-10-12 17:50:54 +02001125 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->level = get_log_level(args[3]);
1128 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001130 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001131 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132 }
1133 }
1134
William Lallemand0f99e342011-10-12 17:50:54 +02001135 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001136 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001137 logsrv->minlvl = get_log_level(args[4]);
1138 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001139 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001140 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001141 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001142 }
1143 }
1144
Robert Tsai81ae1952007-12-05 10:47:29 +01001145 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001146 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001147 if (!sk) {
1148 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001149 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001150 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001151 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001152 goto out;
1153 }
William Lallemand0f99e342011-10-12 17:50:54 +02001154 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001155 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001156 struct sockaddr_storage *sk;
1157 int port1, port2;
1158
Willy Tarreaud393a622013-03-04 18:22:00 +01001159 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001160 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001161 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n", file, linenum, args[0], args[1]);
1162 err_code |= ERR_ALERT | ERR_FATAL;
1163 free(logsrv);
1164 goto out;
1165 }
1166
1167 if (port1 != port2) {
1168 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1169 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001170 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001171 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001172 goto out;
1173 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001174
William Lallemand0f99e342011-10-12 17:50:54 +02001175 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001176 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001177 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179
William Lallemand0f99e342011-10-12 17:50:54 +02001180 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001181 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001182 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1183 char *name;
1184 int len;
1185
1186 if (global.log_send_hostname != NULL) {
1187 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT;
1189 goto out;
1190 }
1191
1192 if (*(args[1]))
1193 name = args[1];
1194 else
1195 name = hostname;
1196
1197 len = strlen(name);
1198
1199 /* We'll add a space after the name to respect the log format */
1200 free(global.log_send_hostname);
1201 global.log_send_hostname = malloc(len + 2);
1202 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1203 }
Kevinm48936af2010-12-22 16:08:21 +00001204 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209 }
1210 free(global.log_tag);
1211 global.log_tag = strdup(args[1]);
1212 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001213 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1214 if (global.spread_checks != 0) {
1215 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001216 err_code |= ERR_ALERT;
1217 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001218 }
1219 if (*(args[1]) == 0) {
1220 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001223 }
1224 global.spread_checks = atol(args[1]);
1225 if (global.spread_checks < 0 || global.spread_checks > 50) {
1226 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001227 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001229 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001230 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1231#ifdef USE_CPU_AFFINITY
1232 int cur_arg, i;
1233 unsigned int proc = 0;
1234 unsigned long cpus = 0;
1235
1236 if (strcmp(args[1], "all") == 0)
1237 proc = 0xFFFFFFFF;
1238 else if (strcmp(args[1], "odd") == 0)
1239 proc = 0x55555555;
1240 else if (strcmp(args[1], "even") == 0)
1241 proc = 0xAAAAAAAA;
1242 else {
1243 proc = atoi(args[1]);
1244 if (proc >= 1 && proc <= 32)
1245 proc = 1 << (proc - 1);
1246 }
1247
1248 if (!proc || !*args[2]) {
1249 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1250 file, linenum, args[0]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254
1255 cur_arg = 2;
1256 while (*args[cur_arg]) {
1257 unsigned int low, high;
1258
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001259 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001260 char *dash = strchr(args[cur_arg], '-');
1261
1262 low = high = str2uic(args[cur_arg]);
1263 if (dash)
1264 high = str2uic(dash + 1);
1265
1266 if (high < low) {
1267 unsigned int swap = low;
1268 low = high;
1269 high = swap;
1270 }
1271
1272 if (low < 0 || high >= sizeof(long) * 8) {
1273 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1274 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278
1279 while (low <= high)
1280 cpus |= 1UL << low++;
1281 }
1282 else {
1283 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1284 file, linenum, args[0], args[cur_arg]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288 cur_arg++;
1289 }
1290 for (i = 0; i < 32; i++)
1291 if (proc & (1 << i))
1292 global.cpu_map[i] = cpus;
1293#else
1294 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297#endif
1298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001300 struct cfg_kw_list *kwl;
1301 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001303
1304 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1305 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1306 if (kwl->kw[index].section != CFG_GLOBAL)
1307 continue;
1308 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001309 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001310 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001311 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001312 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001313 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001314 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001315 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001316 err_code |= ERR_WARN;
1317 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001318 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001319 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001320 }
1321 }
1322 }
1323
Willy Tarreaubaaee002006-06-26 02:48:02 +02001324 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001327
Willy Tarreau058e9072009-07-20 09:30:05 +02001328 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001329 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001330 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331}
1332
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001333void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001335 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 defproxy.mode = PR_MODE_TCP;
1337 defproxy.state = PR_STNEW;
1338 defproxy.maxconn = cfg_maxpconn;
1339 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001340
1341 defproxy.defsrv.inter = DEF_CHKINTR;
1342 defproxy.defsrv.fastinter = 0;
1343 defproxy.defsrv.downinter = 0;
1344 defproxy.defsrv.rise = DEF_RISETIME;
1345 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001346 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001347 defproxy.defsrv.maxqueue = 0;
1348 defproxy.defsrv.minconn = 0;
1349 defproxy.defsrv.maxconn = 0;
1350 defproxy.defsrv.slowstart = 0;
1351 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1352 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1353 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354}
1355
Willy Tarreauade5ec42010-01-28 19:33:49 +01001356
1357static int create_cond_regex_rule(const char *file, int line,
1358 struct proxy *px, int dir, int action, int flags,
1359 const char *cmd, const char *reg, const char *repl,
1360 const char **cond_start)
1361{
1362 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001363 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001364 const char *err;
1365 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001366 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001367
1368 if (px == &defproxy) {
1369 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1370 err_code |= ERR_ALERT | ERR_FATAL;
1371 goto err;
1372 }
1373
1374 if (*reg == 0) {
1375 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto err;
1378 }
1379
1380 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1381 err_code |= ERR_WARN;
1382
Willy Tarreau5321c422010-01-28 20:35:13 +01001383 if (cond_start &&
1384 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001385 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1386 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1387 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001388 err_code |= ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391 }
1392 else if (cond_start && **cond_start) {
1393 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1394 file, line, cmd, *cond_start);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto err;
1397 }
1398
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001399 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001400 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001401 else
1402 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001403
Willy Tarreauade5ec42010-01-28 19:33:49 +01001404 preg = calloc(1, sizeof(regex_t));
1405 if (!preg) {
1406 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1407 err_code = ERR_ALERT | ERR_FATAL;
1408 goto err;
1409 }
1410
1411 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1412 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1413 err_code = ERR_ALERT | ERR_FATAL;
1414 goto err;
1415 }
1416
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001417 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001418 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001419 if (repl && err) {
1420 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1421 file, line, cmd, *err);
1422 err_code |= ERR_ALERT | ERR_FATAL;
1423 goto err;
1424 }
1425
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001426 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001427 err_code |= ERR_WARN;
1428
Willy Tarreauf4068b62012-05-08 17:37:49 +02001429 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001430 return err_code;
1431 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001432 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001433 free(preg);
1434 return err_code;
1435}
1436
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001438 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001439 * Returns the error code, 0 if OK, or any combination of :
1440 * - ERR_ABORT: must abort ASAP
1441 * - ERR_FATAL: we can continue parsing but not start the service
1442 * - ERR_WARN: a warning has been emitted
1443 * - ERR_ALERT: an alert has been emitted
1444 * Only the two first ones can stop processing, the two others are just
1445 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001447int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1448{
1449 static struct peers *curpeers = NULL;
1450 struct peer *newpeer = NULL;
1451 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001452 struct bind_conf *bind_conf;
1453 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001454 int err_code = 0;
1455
1456 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001457 if (!*args[1]) {
1458 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1459 err_code |= ERR_ALERT | ERR_FATAL;
1460 goto out;
1461 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001462
1463 err = invalid_char(args[1]);
1464 if (err) {
1465 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1466 file, linenum, *err, args[0], args[1]);
1467 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001468 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001469 }
1470
1471 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1472 /*
1473 * If there are two proxies with the same name only following
1474 * combinations are allowed:
1475 */
1476 if (strcmp(curpeers->id, args[1]) == 0) {
1477 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1478 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1479 err_code |= ERR_WARN;
1480 }
1481 }
1482
1483 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1484 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1485 err_code |= ERR_ALERT | ERR_ABORT;
1486 goto out;
1487 }
1488
1489 curpeers->next = peers;
1490 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001491 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001492 curpeers->conf.line = linenum;
1493 curpeers->last_change = now.tv_sec;
1494 curpeers->id = strdup(args[1]);
1495 }
1496 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001497 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001498 int port1, port2;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001499 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001500
1501 if (!*args[2]) {
1502 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1503 file, linenum, args[0]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
1506 }
1507
1508 err = invalid_char(args[1]);
1509 if (err) {
1510 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1511 file, linenum, *err, args[1]);
1512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
1514 }
1515
1516 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1517 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1518 err_code |= ERR_ALERT | ERR_ABORT;
1519 goto out;
1520 }
1521
1522 /* the peers are linked backwards first */
1523 curpeers->count++;
1524 newpeer->next = curpeers->remote;
1525 curpeers->remote = newpeer;
1526 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001527 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001528 newpeer->conf.line = linenum;
1529
1530 newpeer->last_change = now.tv_sec;
1531 newpeer->id = strdup(args[1]);
1532
Willy Tarreaud393a622013-03-04 18:22:00 +01001533 sk = str2sa_range(args[2], &port1, &port2, NULL, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001534 if (!sk) {
1535 Alert("parsing [%s:%d] : '%s %s' : unknown host in '%s'\n", file, linenum, args[0], args[1], args[2]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001538 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001539
1540 if (port1 != port2) {
1541 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1542 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
1544 goto out;
1545 }
1546
Willy Tarreau2aa38802013-02-20 19:20:59 +01001547 if (!port1) {
1548 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1549 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001550 err_code |= ERR_ALERT | ERR_FATAL;
1551 goto out;
1552 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001553
Emeric Brun32da3c42010-09-23 18:39:19 +02001554 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001555 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001556 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001557 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001558
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001559 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001560 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1561 file, linenum, newpeer->addr.ss_family, args[2]);
1562 err_code |= ERR_ALERT | ERR_FATAL;
1563 goto out;
1564 }
1565
Emeric Brun32da3c42010-09-23 18:39:19 +02001566 if (strcmp(newpeer->id, localpeer) == 0) {
1567 /* Current is local peer, it define a frontend */
1568 newpeer->local = 1;
1569
1570 if (!curpeers->peers_fe) {
1571 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1572 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1573 err_code |= ERR_ALERT | ERR_ABORT;
1574 goto out;
1575 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001576
Willy Tarreau237250c2011-07-29 01:49:03 +02001577 init_new_proxy(curpeers->peers_fe);
1578 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001579
1580 curpeers->peers_fe->last_change = now.tv_sec;
1581 curpeers->peers_fe->id = strdup(args[1]);
1582 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001583 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1585 curpeers->peers_fe->timeout.connect = 5000;
1586 curpeers->peers_fe->accept = peer_accept;
1587 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001588 curpeers->peers_fe->conf.file = strdup(file);
1589 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001590
1591 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1592
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001593 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1594 if (err_msg && *err_msg) {
1595 indent_msg(&err_msg, 2);
1596 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1597 }
1598 else
1599 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1600 file, linenum, args[0], args[1], args[2]);
1601 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 err_code |= ERR_FATAL;
1603 goto out;
1604 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001605
1606 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1607 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1608 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1609 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1610 l->accept = session_accept;
1611 l->handler = process_session;
1612 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1613 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1614 global.maxsock += l->maxconn;
1615 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001616 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001617 else {
1618 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1619 file, linenum, args[0], args[1],
1620 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1621 err_code |= ERR_FATAL;
1622 goto out;
1623 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001624 }
1625 } /* neither "peer" nor "peers" */
1626 else if (*args[0] != 0) {
1627 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1628 err_code |= ERR_ALERT | ERR_FATAL;
1629 goto out;
1630 }
1631
1632out:
1633 return err_code;
1634}
1635
1636
Willy Tarreau3842f002009-06-14 11:39:52 +02001637int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638{
1639 static struct proxy *curproxy = NULL;
1640 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001641 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001642 int rc;
1643 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001644 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001645 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001646 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001647 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001648 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649
Willy Tarreau977b8e42006-12-29 14:19:17 +01001650 if (!strcmp(args[0], "listen"))
1651 rc = PR_CAP_LISTEN;
1652 else if (!strcmp(args[0], "frontend"))
1653 rc = PR_CAP_FE | PR_CAP_RS;
1654 else if (!strcmp(args[0], "backend"))
1655 rc = PR_CAP_BE | PR_CAP_RS;
1656 else if (!strcmp(args[0], "ruleset"))
1657 rc = PR_CAP_RS;
1658 else
1659 rc = PR_CAP_NONE;
1660
1661 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 if (!*args[1]) {
1663 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1664 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001666 err_code |= ERR_ALERT | ERR_ABORT;
1667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001669
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001670 err = invalid_char(args[1]);
1671 if (err) {
1672 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1673 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001675 }
1676
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001677 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1678 /*
1679 * If there are two proxies with the same name only following
1680 * combinations are allowed:
1681 *
1682 * listen backend frontend ruleset
1683 * listen - - - -
1684 * backend - - OK -
1685 * frontend - OK - -
1686 * ruleset - - - -
1687 */
1688
1689 if (!strcmp(curproxy->id, args[1]) &&
1690 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1691 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001692 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1693 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1694 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001696 }
1697 }
1698
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1700 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001701 err_code |= ERR_ALERT | ERR_ABORT;
1702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001703 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001704
Willy Tarreau97cb7802010-01-03 20:23:58 +01001705 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 curproxy->next = proxy;
1707 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001708 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001709 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001710 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001712 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713
1714 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001715 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001716 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001717 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001718
Willy Tarreau4348fad2012-09-20 16:48:07 +02001719 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1720
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001721 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1722 if (err_msg && *err_msg) {
1723 indent_msg(&err_msg, 2);
1724 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1725 }
1726 else
1727 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1728 file, linenum, args[0], args[1], args[2]);
1729 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_FATAL;
1731 goto out;
1732 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001733
Willy Tarreau4348fad2012-09-20 16:48:07 +02001734 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001735 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 }
1738
1739 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001740 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001741 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001742
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001745 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001746 curproxy->no_options = defproxy.no_options;
1747 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001748 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001749 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001750 curproxy->except_net = defproxy.except_net;
1751 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001752 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001753 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001755 if (defproxy.fwdfor_hdr_len) {
1756 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1757 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1758 }
1759
Willy Tarreaub86db342009-11-30 11:50:16 +01001760 if (defproxy.orgto_hdr_len) {
1761 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1762 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1763 }
1764
Mark Lamourinec2247f02012-01-04 13:02:01 -05001765 if (defproxy.server_id_hdr_len) {
1766 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1767 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1768 }
1769
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 if (curproxy->cap & PR_CAP_FE) {
1771 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001772 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001773 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001774
1775 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001776 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1777 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001778
1779 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781
Willy Tarreau977b8e42006-12-29 14:19:17 +01001782 if (curproxy->cap & PR_CAP_BE) {
1783 curproxy->fullconn = defproxy.fullconn;
1784 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001786 if (defproxy.check_req) {
1787 curproxy->check_req = calloc(1, defproxy.check_len);
1788 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1789 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001792 if (defproxy.expect_str) {
1793 curproxy->expect_str = strdup(defproxy.expect_str);
1794 if (defproxy.expect_regex) {
1795 /* note: this regex is known to be valid */
1796 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1797 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1798 }
1799 }
1800
Willy Tarreau67402132012-05-31 20:40:20 +02001801 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (defproxy.cookie_name)
1803 curproxy->cookie_name = strdup(defproxy.cookie_name);
1804 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001805 if (defproxy.cookie_domain)
1806 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001807
Willy Tarreau31936852010-10-06 16:59:56 +02001808 if (defproxy.cookie_maxidle)
1809 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1810
1811 if (defproxy.cookie_maxlife)
1812 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1813
Emeric Brun647caf12009-06-30 17:57:00 +02001814 if (defproxy.rdp_cookie_name)
1815 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1816 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1817
Willy Tarreau01732802007-11-01 22:48:15 +01001818 if (defproxy.url_param_name)
1819 curproxy->url_param_name = strdup(defproxy.url_param_name);
1820 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001821
Benoitaffb4812009-03-25 13:02:10 +01001822 if (defproxy.hh_name)
1823 curproxy->hh_name = strdup(defproxy.hh_name);
1824 curproxy->hh_len = defproxy.hh_len;
1825 curproxy->hh_match_domain = defproxy.hh_match_domain;
1826
Willy Tarreauef9a3602012-12-08 22:29:20 +01001827 if (defproxy.conn_src.iface_name)
1828 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1829 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1830 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001833 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 if (defproxy.capture_name)
1835 curproxy->capture_name = strdup(defproxy.capture_name);
1836 curproxy->capture_namelen = defproxy.capture_namelen;
1837 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001839
Willy Tarreau977b8e42006-12-29 14:19:17 +01001840 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001841 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001842 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001843 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001844 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845 curproxy->uri_auth = defproxy.uri_auth;
1846 curproxy->mon_net = defproxy.mon_net;
1847 curproxy->mon_mask = defproxy.mon_mask;
1848 if (defproxy.monitor_uri)
1849 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1850 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001851 if (defproxy.defbe.name)
1852 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001853
1854 /* get either a pointer to the logformat string or a copy of it */
1855 curproxy->logformat_string = defproxy.logformat_string;
1856 if (curproxy->logformat_string &&
1857 curproxy->logformat_string != default_http_log_format &&
1858 curproxy->logformat_string != default_tcp_log_format &&
1859 curproxy->logformat_string != clf_http_log_format)
1860 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 }
1862
1863 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001864 curproxy->timeout.connect = defproxy.timeout.connect;
1865 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001866 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001867 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001868 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001869 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001870 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001871 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001872 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001873 }
1874
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001876
1877 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001878 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001879 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001880 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001881 LIST_INIT(&node->list);
1882 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1883 }
1884
Willy Tarreau196729e2012-05-31 19:30:26 +02001885 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1886 if (curproxy->uniqueid_format_string)
1887 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001888
1889 /* copy default header unique id */
1890 if (defproxy.header_unique_id)
1891 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1892
William Lallemand82fe75c2012-10-23 10:25:10 +02001893 /* default compression options */
1894 if (defproxy.comp != NULL) {
1895 curproxy->comp = calloc(1, sizeof(struct comp));
1896 curproxy->comp->algos = defproxy.comp->algos;
1897 curproxy->comp->types = defproxy.comp->types;
1898 }
1899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001901 curproxy->conf.used_listener_id = EB_ROOT;
1902 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001903
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
1906 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1907 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001908 /* FIXME-20070101: we should do this too at the end of the
1909 * config parsing to free all default values.
1910 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001911 free(defproxy.check_req);
1912 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001913 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001914 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001915 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001916 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001917 free(defproxy.capture_name);
1918 free(defproxy.monitor_uri);
1919 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001920 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001921 free(defproxy.fwdfor_hdr_name);
1922 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001923 free(defproxy.orgto_hdr_name);
1924 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001925 free(defproxy.server_id_hdr_name);
1926 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001927 free(defproxy.expect_str);
1928 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001929
Willy Tarreau39b06652012-06-01 10:58:06 +02001930 if (defproxy.logformat_string != default_http_log_format &&
1931 defproxy.logformat_string != default_tcp_log_format &&
1932 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001933 free(defproxy.logformat_string);
1934
1935 free(defproxy.uniqueid_format_string);
1936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001938 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001939
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 /* we cannot free uri_auth because it might already be used */
1941 init_default_instance();
1942 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001943 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
1946 else if (curproxy == NULL) {
1947 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 }
1951
Willy Tarreau977b8e42006-12-29 14:19:17 +01001952
1953 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001955 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001956 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001957 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001958
Willy Tarreaubaaee002006-06-26 02:48:02 +02001959 if (curproxy == &defproxy) {
1960 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966
Emeric Bruned760922010-10-22 17:59:25 +02001967 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001968 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001973
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001974 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001975
1976 /* use default settings for unix sockets */
1977 bind_conf->ux.uid = global.unix_bind.ux.uid;
1978 bind_conf->ux.gid = global.unix_bind.ux.gid;
1979 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001980
1981 /* NOTE: the following line might create several listeners if there
1982 * are comma-separated IPs or port ranges. So all further processing
1983 * will have to be applied to all listeners created after last_listen.
1984 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001985 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1986 if (err_msg && *err_msg) {
1987 indent_msg(&err_msg, 2);
1988 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1989 }
1990 else
1991 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1992 file, linenum, args[0], args[1]);
1993 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
1996 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001997
Willy Tarreau4348fad2012-09-20 16:48:07 +02001998 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1999 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002000 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002001 }
2002
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002003 cur_arg = 2;
2004 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002005 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002006 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002007 char *err;
2008
Willy Tarreau26982662012-09-12 23:17:10 +02002009 kw = bind_find_kw(args[cur_arg]);
2010 if (kw) {
2011 char *err = NULL;
2012 int code;
2013
2014 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002015 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2016 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002017 cur_arg += 1 + kw->skip ;
2018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
2020 }
2021
Willy Tarreau4348fad2012-09-20 16:48:07 +02002022 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002023 err_code |= code;
2024
2025 if (code) {
2026 if (err && *err) {
2027 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002028 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002029 }
2030 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002031 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2032 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002033 if (code & ERR_FATAL) {
2034 free(err);
2035 cur_arg += 1 + kw->skip;
2036 goto out;
2037 }
2038 }
2039 free(err);
2040 cur_arg += 1 + kw->skip;
2041 continue;
2042 }
2043
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 err = NULL;
2045 if (!bind_dumped) {
2046 bind_dump_kws(&err);
2047 indent_msg(&err, 4);
2048 bind_dumped = 1;
2049 }
2050
2051 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2052 file, linenum, args[0], args[1], args[cur_arg],
2053 err ? " Registered keywords :" : "", err ? err : "");
2054 free(err);
2055
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002058 }
Willy Tarreau93893792009-07-23 13:19:11 +02002059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 }
2061 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2062 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2063 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 /* flush useless bits */
2072 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002075 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002076 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002077 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078
Willy Tarreau1c47f852006-07-09 08:22:27 +02002079 if (!*args[1]) {
2080 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002084 }
2085
Willy Tarreaua534fea2008-08-03 12:19:50 +02002086 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002087 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002088 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002089 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002090 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2091
Willy Tarreau93893792009-07-23 13:19:11 +02002092 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2095 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2096 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2097 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2098 else {
2099 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 }
2103 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002104 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002105 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002106
2107 if (curproxy == &defproxy) {
2108 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002112 }
2113
2114 if (!*args[1]) {
2115 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2116 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002119 }
2120
2121 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002122 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002123
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002124 if (curproxy->uuid <= 0) {
2125 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002126 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002129 }
2130
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002131 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2132 if (node) {
2133 struct proxy *target = container_of(node, struct proxy, conf.id);
2134 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2135 file, linenum, proxy_type_str(curproxy), curproxy->id,
2136 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
2139 }
2140 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002141 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002142 else if (!strcmp(args[0], "description")) {
2143 int i, len=0;
2144 char *d;
2145
Cyril Bonté99ed3272010-01-24 23:29:44 +01002146 if (curproxy == &defproxy) {
2147 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2148 file, linenum, args[0]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002153 if (!*args[1]) {
2154 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2155 file, linenum, args[0]);
2156 return -1;
2157 }
2158
2159 for(i=1; *args[i]; i++)
2160 len += strlen(args[i])+1;
2161
2162 d = (char *)calloc(1, len);
2163 curproxy->desc = d;
2164
2165 d += sprintf(d, "%s", args[1]);
2166 for(i=2; *args[i]; i++)
2167 d += sprintf(d, " %s", args[i]);
2168
2169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2171 curproxy->state = PR_STSTOPPED;
2172 }
2173 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2174 curproxy->state = PR_STNEW;
2175 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002176 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2177 int cur_arg = 1;
2178 unsigned int set = 0;
2179
2180 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002181 unsigned int low, high;
2182
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 if (strcmp(args[cur_arg], "all") == 0) {
2184 set = 0;
2185 break;
2186 }
2187 else if (strcmp(args[cur_arg], "odd") == 0) {
2188 set |= 0x55555555;
2189 }
2190 else if (strcmp(args[cur_arg], "even") == 0) {
2191 set |= 0xAAAAAAAA;
2192 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002193 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002194 char *dash = strchr(args[cur_arg], '-');
2195
2196 low = high = str2uic(args[cur_arg]);
2197 if (dash)
2198 high = str2uic(dash + 1);
2199
2200 if (high < low) {
2201 unsigned int swap = low;
2202 low = high;
2203 high = swap;
2204 }
2205
2206 if (low < 1 || high > 32) {
2207 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002211 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002212
2213 if (high > global.nbproc) {
2214 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2215 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002217 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002218 while (low <= high)
2219 set |= 1 << (low++ - 1);
2220 }
2221 else {
2222 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2223 file, linenum, args[0]);
2224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002226 }
2227 cur_arg++;
2228 }
2229 curproxy->bind_proc = set;
2230 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002231 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002232 if (curproxy == &defproxy) {
2233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002236 }
2237
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002238 err = invalid_char(args[1]);
2239 if (err) {
2240 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2241 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002243 }
2244
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002245 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2246 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2247 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002250 }
2251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2253 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 if (*(args[1]) == 0) {
2259 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2260 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002264
Willy Tarreau67402132012-05-31 20:40:20 +02002265 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002266 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002267 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002268 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 curproxy->cookie_name = strdup(args[1]);
2270 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002271
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 cur_arg = 2;
2273 while (*(args[cur_arg])) {
2274 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002275 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 }
2277 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002278 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002281 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002284 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002287 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002289 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002290 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002293 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002295 else if (!strcmp(args[cur_arg], "httponly")) {
2296 curproxy->ck_opts |= PR_CK_HTTPONLY;
2297 }
2298 else if (!strcmp(args[cur_arg], "secure")) {
2299 curproxy->ck_opts |= PR_CK_SECURE;
2300 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002301 else if (!strcmp(args[cur_arg], "domain")) {
2302 if (!*args[cur_arg + 1]) {
2303 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2304 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002307 }
2308
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002309 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002311 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2312 " dots nor does not start with a dot."
2313 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002314 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002315 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002316 }
2317
2318 err = invalid_domainchar(args[cur_arg + 1]);
2319 if (err) {
2320 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2321 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002324 }
2325
Willy Tarreau68a897b2009-12-03 23:28:34 +01002326 if (!curproxy->cookie_domain) {
2327 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2328 } else {
2329 /* one domain was already specified, add another one by
2330 * building the string which will be returned along with
2331 * the cookie.
2332 */
2333 char *new_ptr;
2334 int new_len = strlen(curproxy->cookie_domain) +
2335 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2336 new_ptr = malloc(new_len);
2337 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2338 free(curproxy->cookie_domain);
2339 curproxy->cookie_domain = new_ptr;
2340 }
Willy Tarreau31936852010-10-06 16:59:56 +02002341 cur_arg++;
2342 }
2343 else if (!strcmp(args[cur_arg], "maxidle")) {
2344 unsigned int maxidle;
2345 const char *res;
2346
2347 if (!*args[cur_arg + 1]) {
2348 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2349 file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353
2354 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2355 if (res) {
2356 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2357 file, linenum, *res, args[cur_arg]);
2358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
2360 }
2361 curproxy->cookie_maxidle = maxidle;
2362 cur_arg++;
2363 }
2364 else if (!strcmp(args[cur_arg], "maxlife")) {
2365 unsigned int maxlife;
2366 const char *res;
2367
2368 if (!*args[cur_arg + 1]) {
2369 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2370 file, linenum, args[cur_arg]);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
2373 }
2374
2375 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2376 if (res) {
2377 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2378 file, linenum, *res, args[cur_arg]);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
2382 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002383 cur_arg++;
2384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002386 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 +02002387 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391 cur_arg++;
2392 }
Willy Tarreau67402132012-05-31 20:40:20 +02002393 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2395 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398
Willy Tarreau67402132012-05-31 20:40:20 +02002399 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2401 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002404
Willy Tarreau67402132012-05-31 20:40:20 +02002405 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002406 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2407 file, linenum);
2408 err_code |= ERR_ALERT | ERR_FATAL;
2409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002411 else if (!strcmp(args[0], "persist")) { /* persist */
2412 if (*(args[1]) == 0) {
2413 Alert("parsing [%s:%d] : missing persist method.\n",
2414 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002417 }
2418
2419 if (!strncmp(args[1], "rdp-cookie", 10)) {
2420 curproxy->options2 |= PR_O2_RDPC_PRST;
2421
Emeric Brunb982a3d2010-01-04 15:45:53 +01002422 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002423 const char *beg, *end;
2424
2425 beg = args[1] + 11;
2426 end = strchr(beg, ')');
2427
2428 if (!end || end == beg) {
2429 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2430 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002433 }
2434
2435 free(curproxy->rdp_cookie_name);
2436 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2437 curproxy->rdp_cookie_len = end-beg;
2438 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002439 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002440 free(curproxy->rdp_cookie_name);
2441 curproxy->rdp_cookie_name = strdup("msts");
2442 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2443 }
2444 else { /* syntax */
2445 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2446 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002449 }
2450 }
2451 else {
2452 Alert("parsing [%s:%d] : unknown persist method.\n",
2453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002456 }
2457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002459 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002461 if (curproxy == &defproxy) {
2462 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
2465 }
2466
Willy Tarreau977b8e42006-12-29 14:19:17 +01002467 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002469
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002471 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }
2476 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002477 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 curproxy->appsession_name = strdup(args[1]);
2479 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2480 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002481 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2482 if (err) {
2483 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2484 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002487 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002488 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002489
Willy Tarreau51041c72007-09-09 21:56:53 +02002490 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2491 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_ABORT;
2493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002495
2496 cur_arg = 6;
2497 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002498 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2499 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002500 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002501 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002502 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002503 } else if (!strcmp(args[cur_arg], "prefix")) {
2504 curproxy->options2 |= PR_O2_AS_PFX;
2505 } else if (!strcmp(args[cur_arg], "mode")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
2509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
2511 }
2512
2513 cur_arg++;
2514 if (!strcmp(args[cur_arg], "query-string")) {
2515 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2516 curproxy->options2 |= PR_O2_AS_M_QS;
2517 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2518 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2519 curproxy->options2 |= PR_O2_AS_M_PP;
2520 } else {
2521 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002526 cur_arg++;
2527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 } /* Url App Session */
2529 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002530 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002532
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
2538 }
2539
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 if (*(args[4]) == 0) {
2541 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002546 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 curproxy->capture_name = strdup(args[2]);
2548 curproxy->capture_namelen = strlen(curproxy->capture_name);
2549 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 curproxy->to_log |= LW_COOKIE;
2551 }
2552 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2553 struct cap_hdr *hdr;
2554
2555 if (curproxy == &defproxy) {
2556 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 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
2560
2561 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2562 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2563 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 }
2567
2568 hdr = calloc(sizeof(struct cap_hdr), 1);
2569 hdr->next = curproxy->req_cap;
2570 hdr->name = strdup(args[3]);
2571 hdr->namelen = strlen(args[3]);
2572 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002573 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 hdr->index = curproxy->nb_req_cap++;
2575 curproxy->req_cap = hdr;
2576 curproxy->to_log |= LW_REQHDR;
2577 }
2578 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2579 struct cap_hdr *hdr;
2580
2581 if (curproxy == &defproxy) {
2582 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 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586
2587 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2588 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2589 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
2593 hdr = calloc(sizeof(struct cap_hdr), 1);
2594 hdr->next = curproxy->rsp_cap;
2595 hdr->name = strdup(args[3]);
2596 hdr->namelen = strlen(args[3]);
2597 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002598 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 hdr->index = curproxy->nb_rsp_cap++;
2600 curproxy->rsp_cap = hdr;
2601 curproxy->to_log |= LW_RSPHDR;
2602 }
2603 else {
2604 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619 }
2620 curproxy->conn_retries = atol(args[1]);
2621 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002622 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002623 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002624
2625 if (curproxy == &defproxy) {
2626 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630
Willy Tarreau20b0de52012-12-24 15:45:22 +01002631 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2632 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2633 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2634 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2635 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2636 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002637 file, linenum, args[0]);
2638 err_code |= ERR_WARN;
2639 }
2640
Willy Tarreauff011f22011-01-06 17:51:27 +01002641 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002642
Willy Tarreauff011f22011-01-06 17:51:27 +01002643 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002644 err_code |= ERR_ALERT | ERR_ABORT;
2645 goto out;
2646 }
2647
Willy Tarreauff011f22011-01-06 17:51:27 +01002648 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2649 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002650 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002651 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2652 /* set the header name and length into the proxy structure */
2653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2654 err_code |= ERR_WARN;
2655
2656 if (!*args[1]) {
2657 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2658 file, linenum, args[0]);
2659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
2662
2663 /* set the desired header name */
2664 free(curproxy->server_id_hdr_name);
2665 curproxy->server_id_hdr_name = strdup(args[1]);
2666 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2667 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002668 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002669 if (curproxy == &defproxy) {
2670 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002676 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002680 }
2681
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002682 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2683 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2684 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002687 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002688
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002689 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002690 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002691 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002692 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002693 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002694
Cyril Bonté99ed3272010-01-24 23:29:44 +01002695 if (curproxy == &defproxy) {
2696 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
2699 }
2700
Willy Tarreau4baae242012-12-27 12:00:31 +01002701 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2702 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2703 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002706 }
2707
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002708 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002709 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2710 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002711 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002712 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002713 struct switching_rule *rule;
2714
Willy Tarreaub099aca2008-10-12 17:26:37 +02002715 if (curproxy == &defproxy) {
2716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002719 }
2720
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002723
2724 if (*(args[1]) == 0) {
2725 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728 }
2729
Willy Tarreauef6494c2010-01-28 17:12:36 +01002730 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002731 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2732 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002735 }
2736
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002737 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2738 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2739 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002742 }
2743
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002744 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002745
Willy Tarreau55ea7572007-06-17 19:56:27 +02002746 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2747 rule->cond = cond;
2748 rule->be.name = strdup(args[1]);
2749 LIST_INIT(&rule->list);
2750 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2751 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002752 else if (strcmp(args[0], "use-server") == 0) {
2753 struct server_rule *rule;
2754
2755 if (curproxy == &defproxy) {
2756 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760
2761 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2762 err_code |= ERR_WARN;
2763
2764 if (*(args[1]) == 0) {
2765 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
2770 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2771 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2772 file, linenum, args[0]);
2773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
2775 }
2776
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002777 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2778 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2779 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
2783
2784 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2785
2786 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2787 rule->cond = cond;
2788 rule->srv.name = strdup(args[1]);
2789 LIST_INIT(&rule->list);
2790 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2791 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2792 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002793 else if ((!strcmp(args[0], "force-persist")) ||
2794 (!strcmp(args[0], "ignore-persist"))) {
2795 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002796
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
2803 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2804 err_code |= ERR_WARN;
2805
Willy Tarreauef6494c2010-01-28 17:12:36 +01002806 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002807 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2808 file, linenum, args[0]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002813 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2814 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2815 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002820 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002821
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002822 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002823 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002824 if (!strcmp(args[0], "force-persist")) {
2825 rule->type = PERSIST_TYPE_FORCE;
2826 } else {
2827 rule->type = PERSIST_TYPE_IGNORE;
2828 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002829 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002830 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002831 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 else if (!strcmp(args[0], "stick-table")) {
2833 int myidx = 1;
2834
Emeric Brun32da3c42010-09-23 18:39:19 +02002835 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002836 curproxy->table.type = (unsigned int)-1;
2837 while (*args[myidx]) {
2838 const char *err;
2839
2840 if (strcmp(args[myidx], "size") == 0) {
2841 myidx++;
2842 if (!*(args[myidx])) {
2843 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2844 file, linenum, args[myidx-1]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2849 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2850 file, linenum, *err, args[myidx-1]);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002854 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002855 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002856 else if (strcmp(args[myidx], "peers") == 0) {
2857 myidx++;
2858 if (!*(args[myidx])) {
2859 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2860 file, linenum, args[myidx-1]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864 curproxy->table.peers.name = strdup(args[myidx++]);
2865 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 else if (strcmp(args[myidx], "expire") == 0) {
2867 myidx++;
2868 if (!*(args[myidx])) {
2869 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2870 file, linenum, args[myidx-1]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2875 if (err) {
2876 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2877 file, linenum, *err, args[myidx-1]);
2878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
2880 }
2881 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002882 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002883 }
2884 else if (strcmp(args[myidx], "nopurge") == 0) {
2885 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002886 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002887 }
2888 else if (strcmp(args[myidx], "type") == 0) {
2889 myidx++;
2890 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2891 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2892 file, linenum, args[myidx]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002896 /* myidx already points to next arg */
2897 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002898 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002899 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002900 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002901
2902 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002903 nw = args[myidx];
2904 while (*nw) {
2905 /* the "store" keyword supports a comma-separated list */
2906 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002907 sa = NULL; /* store arg */
2908 while (*nw && *nw != ',') {
2909 if (*nw == '(') {
2910 *nw = 0;
2911 sa = ++nw;
2912 while (*nw != ')') {
2913 if (!*nw) {
2914 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2915 file, linenum, args[0], cw);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919 nw++;
2920 }
2921 *nw = '\0';
2922 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002923 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002924 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002925 if (*nw)
2926 *nw++ = '\0';
2927 type = stktable_get_data_type(cw);
2928 if (type < 0) {
2929 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2930 file, linenum, args[0], cw);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
Willy Tarreauac782882010-06-20 10:41:54 +02002934
2935 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2936 switch (err) {
2937 case PE_NONE: break;
2938 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002939 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2940 file, linenum, args[0], cw);
2941 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002942 break;
2943
2944 case PE_ARG_MISSING:
2945 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2946 file, linenum, args[0], cw);
2947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
2949
2950 case PE_ARG_NOT_USED:
2951 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2952 file, linenum, args[0], cw);
2953 err_code |= ERR_ALERT | ERR_FATAL;
2954 goto out;
2955
2956 default:
2957 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2958 file, linenum, args[0], cw);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002961 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002962 }
2963 myidx++;
2964 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002965 else {
2966 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2967 file, linenum, args[myidx]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 }
2972
2973 if (!curproxy->table.size) {
2974 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2975 file, linenum);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
2980 if (curproxy->table.type == (unsigned int)-1) {
2981 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2982 file, linenum);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986 }
2987 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002988 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002989 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002990 int myidx = 0;
2991 const char *name = NULL;
2992 int flags;
2993
2994 if (curproxy == &defproxy) {
2995 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
3000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3001 err_code |= ERR_WARN;
3002 goto out;
3003 }
3004
3005 myidx++;
3006 if ((strcmp(args[myidx], "store") == 0) ||
3007 (strcmp(args[myidx], "store-request") == 0)) {
3008 myidx++;
3009 flags = STK_IS_STORE;
3010 }
3011 else if (strcmp(args[myidx], "store-response") == 0) {
3012 myidx++;
3013 flags = STK_IS_STORE | STK_ON_RSP;
3014 }
3015 else if (strcmp(args[myidx], "match") == 0) {
3016 myidx++;
3017 flags = STK_IS_MATCH;
3018 }
3019 else if (strcmp(args[myidx], "on") == 0) {
3020 myidx++;
3021 flags = STK_IS_MATCH | STK_IS_STORE;
3022 }
3023 else {
3024 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027 }
3028
3029 if (*(args[myidx]) == 0) {
3030 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
3033 }
3034
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003035 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003037 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
3040 }
3041
3042 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003043 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3045 file, linenum, args[0], expr->fetch->kw);
3046 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003047 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 goto out;
3049 }
3050 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003051 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003052 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3053 file, linenum, args[0], expr->fetch->kw);
3054 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003055 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003056 goto out;
3057 }
3058 }
3059
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003060 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3061 if (expr->fetch->cap & SMP_CAP_L7)
3062 curproxy->acl_requires |= ACL_USE_L7_ANY;
3063
Emeric Brunb982a3d2010-01-04 15:45:53 +01003064 if (strcmp(args[myidx], "table") == 0) {
3065 myidx++;
3066 name = args[myidx++];
3067 }
3068
Willy Tarreauef6494c2010-01-28 17:12:36 +01003069 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003070 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3071 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3072 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003073 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003074 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003075 goto out;
3076 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003077 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003078 else if (*(args[myidx])) {
3079 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3080 file, linenum, args[0], args[myidx]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003082 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003083 goto out;
3084 }
Emeric Brun97679e72010-09-23 17:56:44 +02003085 if (flags & STK_ON_RSP)
3086 err_code |= warnif_cond_requires_req(cond, file, linenum);
3087 else
3088 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003089
Emeric Brunb982a3d2010-01-04 15:45:53 +01003090 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3091 rule->cond = cond;
3092 rule->expr = expr;
3093 rule->flags = flags;
3094 rule->table.name = name ? strdup(name) : NULL;
3095 LIST_INIT(&rule->list);
3096 if (flags & STK_ON_RSP)
3097 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3098 else
3099 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003102 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003103 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003104
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3106 curproxy->uri_auth = NULL; /* we must detach from the default config */
3107
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003108 if (!*args[1]) {
3109 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003110 } else if (!strcmp(args[1], "admin")) {
3111 struct stats_admin_rule *rule;
3112
3113 if (curproxy == &defproxy) {
3114 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
3118
3119 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3120 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3121 err_code |= ERR_ALERT | ERR_ABORT;
3122 goto out;
3123 }
3124
3125 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3126 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3127 file, linenum, args[0], args[1]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003131 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3132 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3133 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
3136 }
3137
3138 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3139
3140 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3141 rule->cond = cond;
3142 LIST_INIT(&rule->list);
3143 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003144 } else if (!strcmp(args[1], "uri")) {
3145 if (*(args[2]) == 0) {
3146 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3150 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003151 err_code |= ERR_ALERT | ERR_ABORT;
3152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
3154 } else if (!strcmp(args[1], "realm")) {
3155 if (*(args[2]) == 0) {
3156 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003161 err_code |= ERR_ALERT | ERR_ABORT;
3162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003164 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003165 unsigned interval;
3166
3167 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3168 if (err) {
3169 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3170 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003173 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3174 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_ALERT | ERR_ABORT;
3176 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003177 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003178 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003179 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003180
3181 if (curproxy == &defproxy) {
3182 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
3185 }
3186
3187 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3188 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3189 err_code |= ERR_ALERT | ERR_ABORT;
3190 goto out;
3191 }
3192
Willy Tarreauff011f22011-01-06 17:51:27 +01003193 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3194 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003195 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3196 file, linenum, args[0]);
3197 err_code |= ERR_WARN;
3198 }
3199
Willy Tarreauff011f22011-01-06 17:51:27 +01003200 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003201
Willy Tarreauff011f22011-01-06 17:51:27 +01003202 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003203 err_code |= ERR_ALERT | ERR_ABORT;
3204 goto out;
3205 }
3206
Willy Tarreauff011f22011-01-06 17:51:27 +01003207 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3208 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003209
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 } else if (!strcmp(args[1], "auth")) {
3211 if (*(args[2]) == 0) {
3212 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003217 err_code |= ERR_ALERT | ERR_ABORT;
3218 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219 }
3220 } else if (!strcmp(args[1], "scope")) {
3221 if (*(args[2]) == 0) {
3222 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 }
3230 } else if (!strcmp(args[1], "enable")) {
3231 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3232 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003236 } else if (!strcmp(args[1], "hide-version")) {
3237 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3238 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003239 err_code |= ERR_ALERT | ERR_ABORT;
3240 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003241 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003242 } else if (!strcmp(args[1], "show-legends")) {
3243 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3244 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3245 err_code |= ERR_ALERT | ERR_ABORT;
3246 goto out;
3247 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003248 } else if (!strcmp(args[1], "show-node")) {
3249
3250 if (*args[2]) {
3251 int i;
3252 char c;
3253
3254 for (i=0; args[2][i]; i++) {
3255 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003256 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3257 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003258 break;
3259 }
3260
3261 if (!i || args[2][i]) {
3262 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3263 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3264 file, linenum, args[0], args[1]);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267 }
3268 }
3269
3270 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3271 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3272 err_code |= ERR_ALERT | ERR_ABORT;
3273 goto out;
3274 }
3275 } else if (!strcmp(args[1], "show-desc")) {
3276 char *desc = NULL;
3277
3278 if (*args[2]) {
3279 int i, len=0;
3280 char *d;
3281
3282 for(i=2; *args[i]; i++)
3283 len += strlen(args[i])+1;
3284
3285 desc = d = (char *)calloc(1, len);
3286
3287 d += sprintf(d, "%s", args[2]);
3288 for(i=3; *args[i]; i++)
3289 d += sprintf(d, " %s", args[i]);
3290 }
3291
3292 if (!*args[2] && !global.desc)
3293 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3294 file, linenum, args[1]);
3295 else {
3296 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3297 free(desc);
3298 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3299 err_code |= ERR_ALERT | ERR_ABORT;
3300 goto out;
3301 }
3302 free(desc);
3303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003305stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003306 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 +01003307 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 }
3312 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003313 int optnum;
3314
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003315 if (*(args[1]) == '\0') {
3316 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3317 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003321
3322 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3323 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003324 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3325 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3326 file, linenum, cfg_opts[optnum].name);
3327 err_code |= ERR_ALERT | ERR_FATAL;
3328 goto out;
3329 }
Willy Tarreau93893792009-07-23 13:19:11 +02003330 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3331 err_code |= ERR_WARN;
3332 goto out;
3333 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003334
Willy Tarreau3842f002009-06-14 11:39:52 +02003335 curproxy->no_options &= ~cfg_opts[optnum].val;
3336 curproxy->options &= ~cfg_opts[optnum].val;
3337
3338 switch (kwm) {
3339 case KWM_STD:
3340 curproxy->options |= cfg_opts[optnum].val;
3341 break;
3342 case KWM_NO:
3343 curproxy->no_options |= cfg_opts[optnum].val;
3344 break;
3345 case KWM_DEF: /* already cleared */
3346 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003347 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003348
Willy Tarreau93893792009-07-23 13:19:11 +02003349 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003350 }
3351 }
3352
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003353 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3354 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003355 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3356 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3357 file, linenum, cfg_opts2[optnum].name);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
Willy Tarreau93893792009-07-23 13:19:11 +02003361 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3362 err_code |= ERR_WARN;
3363 goto out;
3364 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003365
Willy Tarreau3842f002009-06-14 11:39:52 +02003366 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3367 curproxy->options2 &= ~cfg_opts2[optnum].val;
3368
3369 switch (kwm) {
3370 case KWM_STD:
3371 curproxy->options2 |= cfg_opts2[optnum].val;
3372 break;
3373 case KWM_NO:
3374 curproxy->no_options2 |= cfg_opts2[optnum].val;
3375 break;
3376 case KWM_DEF: /* already cleared */
3377 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003378 }
Willy Tarreau93893792009-07-23 13:19:11 +02003379 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003380 }
3381 }
3382
Willy Tarreau3842f002009-06-14 11:39:52 +02003383 if (kwm != KWM_STD) {
3384 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003385 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003388 }
3389
Emeric Brun3a058f32009-06-30 18:26:00 +02003390 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003391 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003393 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003394 if (*(args[2]) != '\0') {
3395 if (!strcmp(args[2], "clf")) {
3396 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003397 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003398 } else {
3399 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003402 }
3403 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003404 if (curproxy->logformat_string != default_http_log_format &&
3405 curproxy->logformat_string != default_tcp_log_format &&
3406 curproxy->logformat_string != clf_http_log_format)
3407 free(curproxy->logformat_string);
3408 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003409 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003410 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003412 if (curproxy->logformat_string != default_http_log_format &&
3413 curproxy->logformat_string != default_tcp_log_format &&
3414 curproxy->logformat_string != clf_http_log_format)
3415 free(curproxy->logformat_string);
3416 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 else if (!strcmp(args[1], "tcpka")) {
3419 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003420 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422
3423 if (curproxy->cap & PR_CAP_FE)
3424 curproxy->options |= PR_O_TCP_CLI_KA;
3425 if (curproxy->cap & PR_CAP_BE)
3426 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003429 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003430 err_code |= ERR_WARN;
3431
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003433 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003434 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003435 curproxy->options2 &= ~PR_O2_CHK_ANY;
3436 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 if (!*args[2]) { /* no argument */
3438 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3439 curproxy->check_len = strlen(DEF_CHECK_REQ);
3440 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003441 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442 curproxy->check_req = (char *)malloc(reqlen);
3443 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003444 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003446 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 if (*args[4])
3448 reqlen += strlen(args[4]);
3449 else
3450 reqlen += strlen("HTTP/1.0");
3451
3452 curproxy->check_req = (char *)malloc(reqlen);
3453 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003454 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003456 }
3457 else if (!strcmp(args[1], "ssl-hello-chk")) {
3458 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003460 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003461
Willy Tarreaua534fea2008-08-03 12:19:50 +02003462 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003463 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003464 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003465 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
Willy Tarreau23677902007-05-08 23:50:35 +02003467 else if (!strcmp(args[1], "smtpchk")) {
3468 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003469 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003470 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003471 curproxy->options2 &= ~PR_O2_CHK_ANY;
3472 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003473
3474 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3475 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3476 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3477 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3478 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3479 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3480 curproxy->check_req = (char *)malloc(reqlen);
3481 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3482 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3483 } else {
3484 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3485 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3486 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3487 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3488 }
3489 }
3490 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003491 else if (!strcmp(args[1], "lb-agent-chk")) {
3492 /* use dynmaic health check */
3493 free(curproxy->check_req);
3494 curproxy->check_req = NULL;
3495 curproxy->options2 &= ~PR_O2_CHK_ANY;
3496 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3497 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003498 else if (!strcmp(args[1], "pgsql-check")) {
3499 /* use PostgreSQL request to check servers' health */
3500 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3501 err_code |= ERR_WARN;
3502
3503 free(curproxy->check_req);
3504 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003505 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003506 curproxy->options2 |= PR_O2_PGSQL_CHK;
3507
3508 if (*(args[2])) {
3509 int cur_arg = 2;
3510
3511 while (*(args[cur_arg])) {
3512 if (strcmp(args[cur_arg], "user") == 0) {
3513 char * packet;
3514 uint32_t packet_len;
3515 uint32_t pv;
3516
3517 /* suboption header - needs additional argument for it */
3518 if (*(args[cur_arg+1]) == 0) {
3519 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3520 file, linenum, args[0], args[1], args[cur_arg]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524
3525 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3526 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3527 pv = htonl(0x30000); /* protocol version 3.0 */
3528
3529 packet = (char*) calloc(1, packet_len);
3530
3531 memcpy(packet + 4, &pv, 4);
3532
3533 /* copy "user" */
3534 memcpy(packet + 8, "user", 4);
3535
3536 /* copy username */
3537 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3538
3539 free(curproxy->check_req);
3540 curproxy->check_req = packet;
3541 curproxy->check_len = packet_len;
3542
3543 packet_len = htonl(packet_len);
3544 memcpy(packet, &packet_len, 4);
3545 cur_arg += 2;
3546 } else {
3547 /* unknown suboption - catchall */
3548 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3549 file, linenum, args[0], args[1]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553 } /* end while loop */
3554 }
3555 }
3556
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003557 else if (!strcmp(args[1], "redis-check")) {
3558 /* use REDIS PING request to check servers' health */
3559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3560 err_code |= ERR_WARN;
3561
3562 free(curproxy->check_req);
3563 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003564 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003565 curproxy->options2 |= PR_O2_REDIS_CHK;
3566
3567 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3568 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3569 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3570 }
3571
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003572 else if (!strcmp(args[1], "mysql-check")) {
3573 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003574 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3575 err_code |= ERR_WARN;
3576
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003577 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003578 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003579 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003580 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003581
3582 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3583 * const char mysql40_client_auth_pkt[] = {
3584 * "\x0e\x00\x00" // packet length
3585 * "\x01" // packet number
3586 * "\x00\x00" // client capabilities
3587 * "\x00\x00\x01" // max packet
3588 * "haproxy\x00" // username (null terminated string)
3589 * "\x00" // filler (always 0x00)
3590 * "\x01\x00\x00" // packet length
3591 * "\x00" // packet number
3592 * "\x01" // COM_QUIT command
3593 * };
3594 */
3595
3596 if (*(args[2])) {
3597 int cur_arg = 2;
3598
3599 while (*(args[cur_arg])) {
3600 if (strcmp(args[cur_arg], "user") == 0) {
3601 char *mysqluser;
3602 int packetlen, reqlen, userlen;
3603
3604 /* suboption header - needs additional argument for it */
3605 if (*(args[cur_arg+1]) == 0) {
3606 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3607 file, linenum, args[0], args[1], args[cur_arg]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611 mysqluser = args[cur_arg + 1];
3612 userlen = strlen(mysqluser);
3613 packetlen = userlen + 7;
3614 reqlen = packetlen + 9;
3615
3616 free(curproxy->check_req);
3617 curproxy->check_req = (char *)calloc(1, reqlen);
3618 curproxy->check_len = reqlen;
3619
3620 snprintf(curproxy->check_req, 4, "%c%c%c",
3621 ((unsigned char) packetlen & 0xff),
3622 ((unsigned char) (packetlen >> 8) & 0xff),
3623 ((unsigned char) (packetlen >> 16) & 0xff));
3624
3625 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003626 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003627 curproxy->check_req[8] = 1;
3628 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3629 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3630 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3631 cur_arg += 2;
3632 } else {
3633 /* unknown suboption - catchall */
3634 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3635 file, linenum, args[0], args[1]);
3636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
3638 }
3639 } /* end while loop */
3640 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003641 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003642 else if (!strcmp(args[1], "ldap-check")) {
3643 /* use LDAP request to check servers' health */
3644 free(curproxy->check_req);
3645 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003646 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003647 curproxy->options2 |= PR_O2_LDAP_CHK;
3648
3649 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3650 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3651 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3652 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003653 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003654 int cur_arg;
3655
3656 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3657 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003658 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003659
Willy Tarreau87cf5142011-08-19 22:57:24 +02003660 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003661
3662 free(curproxy->fwdfor_hdr_name);
3663 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3664 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3665
3666 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3667 cur_arg = 2;
3668 while (*(args[cur_arg])) {
3669 if (!strcmp(args[cur_arg], "except")) {
3670 /* suboption except - needs additional argument for it */
3671 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3672 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3673 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003676 }
3677 /* flush useless bits */
3678 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003679 cur_arg += 2;
3680 } else if (!strcmp(args[cur_arg], "header")) {
3681 /* suboption header - needs additional argument for it */
3682 if (*(args[cur_arg+1]) == 0) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3684 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003687 }
3688 free(curproxy->fwdfor_hdr_name);
3689 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3690 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3691 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003692 } else if (!strcmp(args[cur_arg], "if-none")) {
3693 curproxy->options &= ~PR_O_FF_ALWAYS;
3694 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003695 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003696 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003697 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003698 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003701 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003702 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003703 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003704 else if (!strcmp(args[1], "originalto")) {
3705 int cur_arg;
3706
3707 /* insert x-original-to field, but not for the IP address listed as an except.
3708 * set default options (ie: bitfield, header name, etc)
3709 */
3710
3711 curproxy->options |= PR_O_ORGTO;
3712
3713 free(curproxy->orgto_hdr_name);
3714 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3715 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3716
Willy Tarreau87cf5142011-08-19 22:57:24 +02003717 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003718 cur_arg = 2;
3719 while (*(args[cur_arg])) {
3720 if (!strcmp(args[cur_arg], "except")) {
3721 /* suboption except - needs additional argument for it */
3722 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3723 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3724 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003727 }
3728 /* flush useless bits */
3729 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3730 cur_arg += 2;
3731 } else if (!strcmp(args[cur_arg], "header")) {
3732 /* suboption header - needs additional argument for it */
3733 if (*(args[cur_arg+1]) == 0) {
3734 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3735 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003738 }
3739 free(curproxy->orgto_hdr_name);
3740 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3741 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3742 cur_arg += 2;
3743 } else {
3744 /* unknown suboption - catchall */
3745 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3746 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003749 }
3750 } /* end while loop */
3751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 else {
3753 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 }
Willy Tarreau93893792009-07-23 13:19:11 +02003757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003758 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003759 else if (!strcmp(args[0], "default_backend")) {
3760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003762
3763 if (*(args[1]) == 0) {
3764 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003767 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003768 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003769 curproxy->defbe.name = strdup(args[1]);
3770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003772 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003775 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 /* enable reconnections to dispatch */
3779 curproxy->options |= PR_O_REDISP;
3780 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003781 else if (!strcmp(args[0], "http-check")) {
3782 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003784
3785 if (strcmp(args[1], "disable-on-404") == 0) {
3786 /* enable a graceful server shutdown on an HTTP 404 response */
3787 curproxy->options |= PR_O_DISABLE404;
3788 }
Willy Tarreauef781042010-01-27 11:53:01 +01003789 else if (strcmp(args[1], "send-state") == 0) {
3790 /* enable emission of the apparent state of a server in HTTP checks */
3791 curproxy->options2 |= PR_O2_CHK_SNDST;
3792 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003793 else if (strcmp(args[1], "expect") == 0) {
3794 const char *ptr_arg;
3795 int cur_arg;
3796
3797 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3798 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
3801 }
3802
3803 cur_arg = 2;
3804 /* consider exclamation marks, sole or at the beginning of a word */
3805 while (*(ptr_arg = args[cur_arg])) {
3806 while (*ptr_arg == '!') {
3807 curproxy->options2 ^= PR_O2_EXP_INV;
3808 ptr_arg++;
3809 }
3810 if (*ptr_arg)
3811 break;
3812 cur_arg++;
3813 }
3814 /* now ptr_arg points to the beginning of a word past any possible
3815 * exclamation mark, and cur_arg is the argument which holds this word.
3816 */
3817 if (strcmp(ptr_arg, "status") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003826 curproxy->expect_str = strdup(args[cur_arg + 1]);
3827 }
3828 else if (strcmp(ptr_arg, "string") == 0) {
3829 if (!*(args[cur_arg + 1])) {
3830 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3831 file, linenum, args[0], args[1], ptr_arg);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003836 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003837 curproxy->expect_str = strdup(args[cur_arg + 1]);
3838 }
3839 else if (strcmp(ptr_arg, "rstatus") == 0) {
3840 if (!*(args[cur_arg + 1])) {
3841 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3842 file, linenum, args[0], args[1], ptr_arg);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003847 free(curproxy->expect_str);
3848 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3849 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003850 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3851 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3852 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3853 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857 }
3858 else if (strcmp(ptr_arg, "rstring") == 0) {
3859 if (!*(args[cur_arg + 1])) {
3860 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3861 file, linenum, args[0], args[1], ptr_arg);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003866 free(curproxy->expect_str);
3867 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3868 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003869 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3870 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3871 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3872 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
3875 }
3876 }
3877 else {
3878 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3879 file, linenum, args[0], args[1], ptr_arg);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003884 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003885 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 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003888 }
3889 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003890 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003891 if (curproxy == &defproxy) {
3892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003895 }
3896
Willy Tarreaub80c2302007-11-30 20:51:32 +01003897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003899
3900 if (strcmp(args[1], "fail") == 0) {
3901 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003902 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003903 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3904 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003907 }
3908
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003909 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3910 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3911 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003914 }
3915 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3916 }
3917 else {
3918 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003921 }
3922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923#ifdef TPROXY
3924 else if (!strcmp(args[0], "transparent")) {
3925 /* enable transparent proxy connections */
3926 curproxy->options |= PR_O_TRANSP;
3927 }
3928#endif
3929 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003930 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003932
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 if (*(args[1]) == 0) {
3934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 }
3938 curproxy->maxconn = atol(args[1]);
3939 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003940 else if (!strcmp(args[0], "backlog")) { /* backlog */
3941 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003943
3944 if (*(args[1]) == 0) {
3945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003946 err_code |= ERR_ALERT | ERR_FATAL;
3947 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003948 }
3949 curproxy->backlog = atol(args[1]);
3950 }
Willy Tarreau86034312006-12-29 00:10:33 +01003951 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003954
Willy Tarreau86034312006-12-29 00:10:33 +01003955 if (*(args[1]) == 0) {
3956 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003959 }
3960 curproxy->fullconn = atol(args[1]);
3961 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3963 if (*(args[1]) == 0) {
3964 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003968 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3969 if (err) {
3970 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3971 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003974 }
3975 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
3977 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003978 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003979 int port1, port2;
3980
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 if (curproxy == &defproxy) {
3982 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003986 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003988
Willy Tarreaud393a622013-03-04 18:22:00 +01003989 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003990 if (!sk) {
3991 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n", file, linenum, args[0], args[1]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995
3996 if (port1 != port2) {
3997 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3998 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004002
4003 if (!port1) {
4004 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4005 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004009
Willy Tarreaud5191e72010-02-09 20:50:45 +01004010 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004011 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
4013 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004016
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004017 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4018 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004023 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4025 err_code |= ERR_WARN;
4026
4027 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4028 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4029 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4030 }
4031 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4032 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4033 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4034 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004035 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4036 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4037 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4038 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004039 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004040 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004047 short realport = 0;
4048 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004055 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057
4058 if (!*args[2]) {
4059 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004064
4065 err = invalid_char(args[1]);
4066 if (err) {
4067 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4068 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004071 }
4072
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004073 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004074 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004075 int port1, port2;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004076
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004077 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4078 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4079 err_code |= ERR_ALERT | ERR_ABORT;
4080 goto out;
4081 }
4082
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004083 /* the servers are linked backwards first */
4084 newsrv->next = curproxy->srv;
4085 curproxy->srv = newsrv;
4086 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004087 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004088 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004090 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004091 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 LIST_INIT(&newsrv->pendconns);
4093 do_check = 0;
4094 newsrv->state = SRV_RUNNING; /* early server setup */
4095 newsrv->last_change = now.tv_sec;
4096 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004099 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 * - IP: => port=+0, relative
4101 * - IP:N => port=N, absolute
4102 * - IP:+N => port=+N, relative
4103 * - IP:-N => port=-N, relative
4104 */
Willy Tarreaud393a622013-03-04 18:22:00 +01004105 sk = str2sa_range(args[2], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004106 if (!sk) {
4107 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004111
4112 if (!port1 || !port2) {
4113 /* no port specified, +offset, -offset */
4114 newsrv->state |= SRV_MAPPORTS;
4115 }
4116 else if (port1 != port2) {
4117 /* port range */
4118 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4119 file, linenum, args[0], args[1], args[2]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123 else {
4124 /* used by checks */
4125 realport = port1;
4126 }
4127
Willy Tarreaud5191e72010-02-09 20:50:45 +01004128 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004129 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4130 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004131
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004132 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004133 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4134 file, linenum, newsrv->addr.ss_family, args[2]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004139 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004140 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004141 newsrv->inter = curproxy->defsrv.inter;
4142 newsrv->fastinter = curproxy->defsrv.fastinter;
4143 newsrv->downinter = curproxy->defsrv.downinter;
4144 newsrv->rise = curproxy->defsrv.rise;
4145 newsrv->fall = curproxy->defsrv.fall;
4146 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4147 newsrv->minconn = curproxy->defsrv.minconn;
4148 newsrv->maxconn = curproxy->defsrv.maxconn;
4149 newsrv->slowstart = curproxy->defsrv.slowstart;
4150 newsrv->onerror = curproxy->defsrv.onerror;
4151 newsrv->consecutive_errors_limit
4152 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004153#ifdef OPENSSL
4154 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4155#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004156 newsrv->uweight = newsrv->iweight
4157 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004159 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004161 cur_arg = 3;
4162 } else {
4163 newsrv = &curproxy->defsrv;
4164 cur_arg = 1;
4165 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004166
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004168 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 newsrv->cookie = strdup(args[cur_arg + 1]);
4170 newsrv->cklen = strlen(args[cur_arg + 1]);
4171 cur_arg += 2;
4172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004173 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004174 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4175 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4176 cur_arg += 2;
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004179 if (!*args[cur_arg + 1]) {
4180 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4181 file, linenum, args[cur_arg]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
4185
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004187 if (newsrv->rise <= 0) {
4188 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4189 file, linenum, args[cur_arg]);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192 }
4193
Willy Tarreau96839092010-03-29 10:02:24 +02004194 if (newsrv->health)
4195 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 cur_arg += 2;
4197 }
4198 else if (!strcmp(args[cur_arg], "fall")) {
4199 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004200
4201 if (!*args[cur_arg + 1]) {
4202 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4203 file, linenum, args[cur_arg]);
4204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
4206 }
4207
4208 if (newsrv->fall <= 0) {
4209 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4210 file, linenum, args[cur_arg]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 cur_arg += 2;
4216 }
4217 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004218 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4219 if (err) {
4220 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4221 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004224 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004225 if (val <= 0) {
4226 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4227 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004230 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004231 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 cur_arg += 2;
4233 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004234 else if (!strcmp(args[cur_arg], "fastinter")) {
4235 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4236 if (err) {
4237 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4238 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004241 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004242 if (val <= 0) {
4243 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4244 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004247 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004248 newsrv->fastinter = val;
4249 cur_arg += 2;
4250 }
4251 else if (!strcmp(args[cur_arg], "downinter")) {
4252 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4253 if (err) {
4254 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4255 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004258 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004259 if (val <= 0) {
4260 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4261 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004264 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004265 newsrv->downinter = val;
4266 cur_arg += 2;
4267 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004268 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004269 struct sockaddr_storage *sk;
4270 int port1, port2;
4271
Willy Tarreaud393a622013-03-04 18:22:00 +01004272 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004273 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004274 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4275 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004279 if (port1 != port2) {
4280 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4281 file, linenum, args[cur_arg], args[cur_arg + 1]);
4282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
4284 }
4285
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004286 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004287 cur_arg += 2;
4288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004290 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 cur_arg += 2;
4292 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004293 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 newsrv->state |= SRV_BACKUP;
4295 cur_arg ++;
4296 }
Simon Hormanfa461682011-06-25 09:39:49 +09004297 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4298 newsrv->state |= SRV_NON_STICK;
4299 cur_arg ++;
4300 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004301 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4302 newsrv->state |= SRV_SEND_PROXY;
4303 cur_arg ++;
4304 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004305 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4306 newsrv->check.send_proxy = 1;
4307 cur_arg ++;
4308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 else if (!strcmp(args[cur_arg], "weight")) {
4310 int w;
4311 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004312 if (w < 0 || w > 256) {
4313 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004318 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 cur_arg += 2;
4320 }
4321 else if (!strcmp(args[cur_arg], "minconn")) {
4322 newsrv->minconn = atol(args[cur_arg + 1]);
4323 cur_arg += 2;
4324 }
4325 else if (!strcmp(args[cur_arg], "maxconn")) {
4326 newsrv->maxconn = atol(args[cur_arg + 1]);
4327 cur_arg += 2;
4328 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004329 else if (!strcmp(args[cur_arg], "maxqueue")) {
4330 newsrv->maxqueue = atol(args[cur_arg + 1]);
4331 cur_arg += 2;
4332 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004333 else if (!strcmp(args[cur_arg], "slowstart")) {
4334 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004335 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004336 if (err) {
4337 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4338 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004341 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004342 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004343 cur_arg += 2;
4344 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004345 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004346
4347 if (!*args[cur_arg + 1]) {
4348 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4349 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004352 }
4353
4354 newsrv->trackit = strdup(args[cur_arg + 1]);
4355
4356 cur_arg += 2;
4357 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004358 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004359 global.maxsock++;
4360 do_check = 1;
4361 cur_arg += 1;
4362 }
Willy Tarreau96839092010-03-29 10:02:24 +02004363 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4364 newsrv->state |= SRV_MAINTAIN;
4365 newsrv->state &= ~SRV_RUNNING;
4366 newsrv->health = 0;
4367 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004368 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004369 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004370 if (!strcmp(args[cur_arg + 1], "none"))
4371 newsrv->observe = HANA_OBS_NONE;
4372 else if (!strcmp(args[cur_arg + 1], "layer4"))
4373 newsrv->observe = HANA_OBS_LAYER4;
4374 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4375 if (curproxy->mode != PR_MODE_HTTP) {
4376 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4377 file, linenum, args[cur_arg + 1]);
4378 err_code |= ERR_ALERT;
4379 }
4380 newsrv->observe = HANA_OBS_LAYER7;
4381 }
4382 else {
4383 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004384 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004385 file, linenum, args[cur_arg], args[cur_arg + 1]);
4386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
4388 }
4389
4390 cur_arg += 2;
4391 }
4392 else if (!strcmp(args[cur_arg], "on-error")) {
4393 if (!strcmp(args[cur_arg + 1], "fastinter"))
4394 newsrv->onerror = HANA_ONERR_FASTINTER;
4395 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4396 newsrv->onerror = HANA_ONERR_FAILCHK;
4397 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4398 newsrv->onerror = HANA_ONERR_SUDDTH;
4399 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4400 newsrv->onerror = HANA_ONERR_MARKDWN;
4401 else {
4402 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004403 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004404 file, linenum, args[cur_arg], args[cur_arg + 1]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
4408
4409 cur_arg += 2;
4410 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004411 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4412 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4413 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4414 else {
4415 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4416 file, linenum, args[cur_arg], args[cur_arg + 1]);
4417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420
4421 cur_arg += 2;
4422 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004423 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4424 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4425 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4426 else {
4427 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4428 file, linenum, args[cur_arg], args[cur_arg + 1]);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432
4433 cur_arg += 2;
4434 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004435 else if (!strcmp(args[cur_arg], "error-limit")) {
4436 if (!*args[cur_arg + 1]) {
4437 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4438 file, linenum, args[cur_arg]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442
4443 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4444
4445 if (newsrv->consecutive_errors_limit <= 0) {
4446 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4447 file, linenum, args[cur_arg]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004451 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004452 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004453 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004454 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004455 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004456
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004458 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4459 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004463 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud393a622013-03-04 18:22:00 +01004464 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004465 if (!sk) {
4466 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004470 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004471
4472 if (port_low != port_high) {
4473 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004474
4475 if (!port_low || !port_high) {
4476 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4477 file, linenum, args[cur_arg], args[cur_arg + 1]);
4478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
4480 }
4481
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004482 if (port_low <= 0 || port_low > 65535 ||
4483 port_high <= 0 || port_high > 65535 ||
4484 port_low > port_high) {
4485 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4486 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004489 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004490 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4491 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4492 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004493 }
4494
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496 while (*(args[cur_arg])) {
4497 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004498#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4499#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004500 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004501 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4502 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004506#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004507 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004508 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004509 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004512 }
4513 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004514 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4515 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004516 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004517 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4518 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004519 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4520 char *name, *end;
4521
4522 name = args[cur_arg+1] + 7;
4523 while (isspace(*name))
4524 name++;
4525
4526 end = name;
4527 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4528 end++;
4529
Willy Tarreauef9a3602012-12-08 22:29:20 +01004530 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4531 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4532 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4533 newsrv->conn_src.bind_hdr_len = end - name;
4534 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4535 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4536 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004537
4538 /* now look for an occurrence number */
4539 while (isspace(*end))
4540 end++;
4541 if (*end == ',') {
4542 end++;
4543 name = end;
4544 if (*end == '-')
4545 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004546 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004547 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004548 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004549 }
4550
Willy Tarreauef9a3602012-12-08 22:29:20 +01004551 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004552 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4553 " occurrences values smaller than %d.\n",
4554 file, linenum, MAX_HDR_HISTORY);
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004558 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004559 struct sockaddr_storage *sk;
4560 int port1, port2;
4561
Willy Tarreaud393a622013-03-04 18:22:00 +01004562 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004563 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004564 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4565 file, linenum, args[cur_arg], args[cur_arg + 1]);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
4569 if (port1 != port2) {
4570 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4571 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004575 newsrv->conn_src.tproxy_addr = *sk;
4576 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004577 }
4578 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004579#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004580 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004581#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004582 cur_arg += 2;
4583 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004584#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004585 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004586 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004589#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4590 } /* "usesrc" */
4591
4592 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4593#ifdef SO_BINDTODEVICE
4594 if (!*args[cur_arg + 1]) {
4595 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004599 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004600 free(newsrv->conn_src.iface_name);
4601 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4602 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004603 global.last_checks |= LSTCHK_NETADM;
4604#else
4605 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4606 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004609#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004610 cur_arg += 2;
4611 continue;
4612 }
4613 /* this keyword in not an option of "source" */
4614 break;
4615 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004617 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004618 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4619 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004624 static int srv_dumped;
4625 struct srv_kw *kw;
4626 char *err;
4627
4628 kw = srv_find_kw(args[cur_arg]);
4629 if (kw) {
4630 char *err = NULL;
4631 int code;
4632
4633 if (!kw->parse) {
4634 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4635 file, linenum, args[0], args[1], args[cur_arg]);
4636 cur_arg += 1 + kw->skip ;
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
4640
4641 if (defsrv && !kw->default_ok) {
4642 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4643 file, linenum, args[0], args[1], args[cur_arg]);
4644 cur_arg += 1 + kw->skip ;
4645 err_code |= ERR_ALERT;
4646 continue;
4647 }
4648
4649 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4650 err_code |= code;
4651
4652 if (code) {
4653 if (err && *err) {
4654 indent_msg(&err, 2);
4655 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4656 }
4657 else
4658 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4659 file, linenum, args[0], args[1], args[cur_arg]);
4660 if (code & ERR_FATAL) {
4661 free(err);
4662 cur_arg += 1 + kw->skip;
4663 goto out;
4664 }
4665 }
4666 free(err);
4667 cur_arg += 1 + kw->skip;
4668 continue;
4669 }
4670
4671 err = NULL;
4672 if (!srv_dumped) {
4673 srv_dump_kws(&err);
4674 indent_msg(&err, 4);
4675 srv_dumped = 1;
4676 }
4677
4678 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4679 file, linenum, args[0], args[1], args[cur_arg],
4680 err ? " Registered keywords :" : "", err ? err : "");
4681 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004682
Willy Tarreau93893792009-07-23 13:19:11 +02004683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 }
4686 }
4687
4688 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004689 if (newsrv->trackit) {
4690 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4691 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004694 }
4695
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004696 /* If neither a port nor an addr was specified and no check transport
4697 * layer is forced, then the transport layer used by the checks is the
4698 * same as for the production traffic. Otherwise we use raw_sock by
4699 * default, unless one is specified.
4700 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004701 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004702#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004703 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004704#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004705 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4706 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004707 /* try to get the port from check.addr if check.port not set */
4708 if (!newsrv->check.port)
4709 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004710
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004711 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004712 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004713
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004714 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004715 /* not yet valid, because no port was set on
4716 * the server either. We'll check if we have
4717 * a known port on the first listener.
4718 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004719 struct listener *l;
4720
4721 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004722 newsrv->check.port = get_host_port(&l->addr);
4723 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004724 break;
4725 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004726 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004727 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4729 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004732 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004733
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004734 /* Allocate buffer for check requests... */
4735 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004736 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4737 err_code |= ERR_ALERT | ERR_ABORT;
4738 goto out;
4739 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004740 newsrv->check.bi->size = global.tune.chksize;
4741
4742 /* Allocate buffer for check responses... */
4743 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4744 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4745 err_code |= ERR_ALERT | ERR_ABORT;
4746 goto out;
4747 }
4748 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004749
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004750 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004751 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004752 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4753 err_code |= ERR_ALERT | ERR_ABORT;
4754 goto out;
4755 }
4756
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004757 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4758 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 newsrv->state |= SRV_CHECKED;
4760 }
4761
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004762 if (!defsrv) {
4763 if (newsrv->state & SRV_BACKUP)
4764 curproxy->srv_bck++;
4765 else
4766 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004767
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004768 newsrv->prev_state = newsrv->state;
4769 }
William Lallemanda73203e2012-03-12 12:48:57 +01004770 }
4771
4772 else if (strcmp(args[0], "unique-id-format") == 0) {
4773 if (!*(args[1])) {
4774 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
William Lallemand3203ff42012-11-11 17:30:56 +01004778 if (*(args[2])) {
4779 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
4782 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004783 free(curproxy->uniqueid_format_string);
4784 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004785 }
William Lallemanda73203e2012-03-12 12:48:57 +01004786
4787 else if (strcmp(args[0], "unique-id-header") == 0) {
4788 if (!*(args[1])) {
4789 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792 }
4793 free(curproxy->header_unique_id);
4794 curproxy->header_unique_id = strdup(args[1]);
4795 }
4796
William Lallemand723b73a2012-02-08 16:37:49 +01004797 else if (strcmp(args[0], "log-format") == 0) {
4798 if (!*(args[1])) {
4799 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
William Lallemand3203ff42012-11-11 17:30:56 +01004803 if (*(args[2])) {
4804 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004808
4809 if (curproxy->logformat_string != default_http_log_format &&
4810 curproxy->logformat_string != default_tcp_log_format &&
4811 curproxy->logformat_string != clf_http_log_format)
4812 free(curproxy->logformat_string);
4813 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
William Lallemand723b73a2012-02-08 16:37:49 +01004815
William Lallemand0f99e342011-10-12 17:50:54 +02004816 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4817 /* delete previous herited or defined syslog servers */
4818 struct logsrv *back;
4819
4820 if (*(args[1]) != 0) {
4821 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
4824 }
4825
William Lallemand723b73a2012-02-08 16:37:49 +01004826 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4827 LIST_DEL(&tmplogsrv->list);
4828 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004829 }
4830 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004832 struct logsrv *logsrv;
4833
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004835 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004836 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004837 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004838 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004839 LIST_INIT(&node->list);
4840 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004844
4845 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846
William Lallemand0f99e342011-10-12 17:50:54 +02004847 logsrv->facility = get_log_facility(args[2]);
4848 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
4852
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
4854
William Lallemand0f99e342011-10-12 17:50:54 +02004855 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004857 logsrv->level = get_log_level(args[3]);
4858 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
4864 }
4865
William Lallemand0f99e342011-10-12 17:50:54 +02004866 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004867 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004868 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004869 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004870 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004871 err_code |= ERR_ALERT | ERR_FATAL;
4872 goto out;
4873
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004874 }
4875 }
4876
Robert Tsai81ae1952007-12-05 10:47:29 +01004877 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004878 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004879 if (!sk) {
4880 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004881 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
William Lallemand0f99e342011-10-12 17:50:54 +02004885 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004886 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004887 struct sockaddr_storage *sk;
4888 int port1, port2;
4889
Willy Tarreaud393a622013-03-04 18:22:00 +01004890 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004891 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004892 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4893 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004897
4898 if (port1 != port2) {
4899 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4900 file, linenum, args[0], args[1]);
4901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
4903 }
4904
William Lallemand0f99e342011-10-12 17:50:54 +02004905 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004906 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004907 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
William Lallemand0f99e342011-10-12 17:50:54 +02004909
4910 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912 else {
4913 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4914 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918 }
4919 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004920 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004921 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004922 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004923
Willy Tarreau977b8e42006-12-29 14:19:17 +01004924 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004926
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004928 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4929 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004933
4934 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004935 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4936 free(curproxy->conn_src.iface_name);
4937 curproxy->conn_src.iface_name = NULL;
4938 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004939
Willy Tarreaud393a622013-03-04 18:22:00 +01004940 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004941 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004942 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4943 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
4946 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004947
4948 if (port1 != port2) {
4949 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4950 file, linenum, args[0], args[1]);
4951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
4953 }
4954
Willy Tarreauef9a3602012-12-08 22:29:20 +01004955 curproxy->conn_src.source_addr = *sk;
4956 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004957
4958 cur_arg = 2;
4959 while (*(args[cur_arg])) {
4960 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004961#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4962#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004963 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004964 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4965 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004968 }
4969#endif
4970 if (!*args[cur_arg + 1]) {
4971 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4972 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975 }
4976
4977 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004978 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4979 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004980 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004981 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4982 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004983 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4984 char *name, *end;
4985
4986 name = args[cur_arg+1] + 7;
4987 while (isspace(*name))
4988 name++;
4989
4990 end = name;
4991 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4992 end++;
4993
Willy Tarreauef9a3602012-12-08 22:29:20 +01004994 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4995 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4996 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4997 curproxy->conn_src.bind_hdr_len = end - name;
4998 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4999 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5000 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005001
5002 /* now look for an occurrence number */
5003 while (isspace(*end))
5004 end++;
5005 if (*end == ',') {
5006 end++;
5007 name = end;
5008 if (*end == '-')
5009 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005010 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005011 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005012 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005013 }
5014
Willy Tarreauef9a3602012-12-08 22:29:20 +01005015 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005016 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5017 " occurrences values smaller than %d.\n",
5018 file, linenum, MAX_HDR_HISTORY);
5019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
5021 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005022 } else {
Willy Tarreaud393a622013-03-04 18:22:00 +01005023 struct sockaddr_storage *sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005024
Willy Tarreaud5191e72010-02-09 20:50:45 +01005025 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005026 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
5027 file, linenum, args[cur_arg], args[cur_arg + 1]);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
5031 if (port1 != port2) {
5032 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5033 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
5036 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005037 curproxy->conn_src.tproxy_addr = *sk;
5038 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005039 }
5040 global.last_checks |= LSTCHK_NETADM;
5041#if !defined(CONFIG_HAP_LINUX_TPROXY)
5042 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005043#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005044#else /* no TPROXY support */
5045 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005046 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049#endif
5050 cur_arg += 2;
5051 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005052 }
5053
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005054 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5055#ifdef SO_BINDTODEVICE
5056 if (!*args[cur_arg + 1]) {
5057 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005061 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005062 free(curproxy->conn_src.iface_name);
5063 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5064 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 global.last_checks |= LSTCHK_NETADM;
5066#else
5067 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5068 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005071#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005072 cur_arg += 2;
5073 continue;
5074 }
5075 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005076 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005081 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5082 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5083 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5090 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094
5095 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005096 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005097 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005098 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 }
5101 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005102 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005103 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005104 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
5108 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005110 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005111 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
5115 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005117 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005118 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005124 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005129 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005131 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005132 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005135 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005136 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005138 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005139 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005141 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005142 }
5143 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005145 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005146 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005148 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5153 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005154 err_code |= ERR_ALERT | ERR_FATAL;
5155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157
5158 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005159 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005160 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 }
5164 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005166 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005167 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005170 }
5171 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005173 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005174 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
5178 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005179 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005180 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005181 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
5185 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005187 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005188 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005192 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005194 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005197 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005200 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005201
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 if (curproxy == &defproxy) {
5203 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005207 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 if (*(args[1]) == 0) {
5211 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005215
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005216 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005217 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5218 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5219 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
5222 }
5223 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5224 }
5225 else if (*args[2]) {
5226 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5227 file, linenum, args[0], args[2]);
5228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230 }
5231
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005232 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005233 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005234 wl->s = strdup(args[1]);
5235 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005236 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5241 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005245
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005248 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
5252 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
5266 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5269 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005276 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
5280 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005289 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005290 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005295 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005296
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 if (curproxy == &defproxy) {
5298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005302 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 if (*(args[1]) == 0) {
5306 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
5310
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005311 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005312 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5313 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5314 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318 err_code |= warnif_cond_requires_req(cond, file, linenum);
5319 }
5320 else if (*args[2]) {
5321 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5322 file, linenum, args[0], args[2]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005327 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005328 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005329 wl->s = strdup(args[1]);
5330 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
5332 else if (!strcmp(args[0], "errorloc") ||
5333 !strcmp(args[0], "errorloc302") ||
5334 !strcmp(args[0], "errorloc303")) { /* error location */
5335 int errnum, errlen;
5336 char *err;
5337
Willy Tarreau977b8e42006-12-29 14:19:17 +01005338 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005340
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005342 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 }
5346
5347 errnum = atol(args[1]);
5348 if (!strcmp(args[0], "errorloc303")) {
5349 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5350 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5351 } else {
5352 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5353 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5354 }
5355
Willy Tarreau0f772532006-12-23 20:51:41 +01005356 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5357 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005358 chunk_destroy(&curproxy->errmsg[rc]);
5359 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005360 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005363
5364 if (rc >= HTTP_ERR_SIZE) {
5365 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5366 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 free(err);
5368 }
5369 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005370 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5371 int errnum, errlen, fd;
5372 char *err;
5373 struct stat stat;
5374
5375 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005376 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005377
5378 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005379 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005382 }
5383
5384 fd = open(args[2], O_RDONLY);
5385 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5386 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5387 file, linenum, args[2], args[1]);
5388 if (fd >= 0)
5389 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005392 }
5393
Willy Tarreau27a674e2009-08-17 07:23:33 +02005394 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005395 errlen = stat.st_size;
5396 } else {
5397 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005398 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005400 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005401 }
5402
5403 err = malloc(errlen); /* malloc() must succeed during parsing */
5404 errnum = read(fd, err, errlen);
5405 if (errnum != errlen) {
5406 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5407 file, linenum, args[2], args[1]);
5408 close(fd);
5409 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005412 }
5413 close(fd);
5414
5415 errnum = atol(args[1]);
5416 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5417 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005418 chunk_destroy(&curproxy->errmsg[rc]);
5419 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005420 break;
5421 }
5422 }
5423
5424 if (rc >= HTTP_ERR_SIZE) {
5425 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5426 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005427 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005428 free(err);
5429 }
5430 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005431 else if (!strcmp(args[0], "compression")) {
5432 struct comp *comp;
5433 if (curproxy->comp == NULL) {
5434 comp = calloc(1, sizeof(struct comp));
5435 curproxy->comp = comp;
5436 } else {
5437 comp = curproxy->comp;
5438 }
5439
5440 if (!strcmp(args[1], "algo")) {
5441 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005442 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005443
William Lallemand82fe75c2012-10-23 10:25:10 +02005444 cur_arg = 2;
5445 if (!*args[cur_arg]) {
5446 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5447 file, linenum, args[0]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451 while (*(args[cur_arg])) {
5452 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5453 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5454 file, linenum, args[0], args[cur_arg]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
William Lallemand552df672012-11-07 13:21:47 +01005458 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5459 curproxy->comp->algos->end(&ctx);
5460 } else {
5461 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5462 file, linenum, args[0], args[cur_arg]);
5463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
5465 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005466 cur_arg ++;
5467 continue;
5468 }
5469 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005470 else if (!strcmp(args[1], "offload")) {
5471 comp->offload = 1;
5472 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005473 else if (!strcmp(args[1], "type")) {
5474 int cur_arg;
5475 cur_arg = 2;
5476 if (!*args[cur_arg]) {
5477 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5478 file, linenum, args[0]);
5479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
5481 }
5482 while (*(args[cur_arg])) {
5483 comp_append_type(comp, args[cur_arg]);
5484 cur_arg ++;
5485 continue;
5486 }
5487 }
5488 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005489 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005490 file, linenum, args[0]);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
5494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005496 struct cfg_kw_list *kwl;
5497 int index;
5498
5499 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5500 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5501 if (kwl->kw[index].section != CFG_LISTEN)
5502 continue;
5503 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5504 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005505 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005506 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005507 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005510 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005511 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005512 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005513 err_code |= ERR_WARN;
5514 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005515 }
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005517 }
5518 }
5519 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005520
Willy Tarreau6daf3432008-01-22 16:44:08 +01005521 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
Willy Tarreau93893792009-07-23 13:19:11 +02005525 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005526 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005527 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528}
5529
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005530int
5531cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5532{
5533
5534 int err_code = 0;
5535 const char *err;
5536
5537 if (!strcmp(args[0], "userlist")) { /* new userlist */
5538 struct userlist *newul;
5539
5540 if (!*args[1]) {
5541 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5542 file, linenum, args[0]);
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
5545 }
5546
5547 err = invalid_char(args[1]);
5548 if (err) {
5549 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5550 file, linenum, *err, args[0], args[1]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554
5555 for (newul = userlist; newul; newul = newul->next)
5556 if (!strcmp(newul->name, args[1])) {
5557 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5558 file, linenum, args[1]);
5559 err_code |= ERR_WARN;
5560 goto out;
5561 }
5562
5563 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5564 if (!newul) {
5565 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5566 err_code |= ERR_ALERT | ERR_ABORT;
5567 goto out;
5568 }
5569
5570 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5571 newul->name = strdup(args[1]);
5572
5573 if (!newul->groupusers | !newul->name) {
5574 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5575 err_code |= ERR_ALERT | ERR_ABORT;
5576 goto out;
5577 }
5578
5579 newul->next = userlist;
5580 userlist = newul;
5581
5582 } else if (!strcmp(args[0], "group")) { /* new group */
5583 int cur_arg, i;
5584 const char *err;
5585
5586 if (!*args[1]) {
5587 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5588 file, linenum, args[0]);
5589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
5591 }
5592
5593 err = invalid_char(args[1]);
5594 if (err) {
5595 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5596 file, linenum, *err, args[0], args[1]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600
5601 for(i = 0; i < userlist->grpcnt; i++)
5602 if (!strcmp(userlist->groups[i], args[1])) {
5603 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5604 file, linenum, args[1], userlist->name);
5605 err_code |= ERR_ALERT;
5606 goto out;
5607 }
5608
5609 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5610 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5611 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
5616 cur_arg = 2;
5617
5618 while (*args[cur_arg]) {
5619 if (!strcmp(args[cur_arg], "users")) {
5620 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5621 cur_arg += 2;
5622 continue;
5623 } else {
5624 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5625 file, linenum, args[0]);
5626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
5628 }
5629 }
5630
5631 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5632 } else if (!strcmp(args[0], "user")) { /* new user */
5633 struct auth_users *newuser;
5634 int cur_arg;
5635
5636 if (!*args[1]) {
5637 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5638 file, linenum, args[0]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642
5643 for (newuser = userlist->users; newuser; newuser = newuser->next)
5644 if (!strcmp(newuser->user, args[1])) {
5645 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5646 file, linenum, args[1], userlist->name);
5647 err_code |= ERR_ALERT;
5648 goto out;
5649 }
5650
5651 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5652 if (!newuser) {
5653 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5654 err_code |= ERR_ALERT | ERR_ABORT;
5655 goto out;
5656 }
5657
5658 newuser->user = strdup(args[1]);
5659
5660 newuser->next = userlist->users;
5661 userlist->users = newuser;
5662
5663 cur_arg = 2;
5664
5665 while (*args[cur_arg]) {
5666 if (!strcmp(args[cur_arg], "password")) {
5667#ifndef CONFIG_HAP_CRYPT
5668 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5669 file, linenum);
5670 err_code |= ERR_ALERT;
5671#endif
5672 newuser->pass = strdup(args[cur_arg + 1]);
5673 cur_arg += 2;
5674 continue;
5675 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5676 newuser->pass = strdup(args[cur_arg + 1]);
5677 newuser->flags |= AU_O_INSECURE;
5678 cur_arg += 2;
5679 continue;
5680 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005681 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005682 cur_arg += 2;
5683 continue;
5684 } else {
5685 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5686 file, linenum, args[0]);
5687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
5689 }
5690 }
5691 } else {
5692 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5693 err_code |= ERR_ALERT | ERR_FATAL;
5694 }
5695
5696out:
5697 return err_code;
5698}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699
5700/*
5701 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005702 * Returns the error code, 0 if OK, or any combination of :
5703 * - ERR_ABORT: must abort ASAP
5704 * - ERR_FATAL: we can continue parsing but not start the service
5705 * - ERR_WARN: a warning has been emitted
5706 * - ERR_ALERT: an alert has been emitted
5707 * Only the two first ones can stop processing, the two others are just
5708 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005710int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005712 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 FILE *f;
5714 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005716 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 if ((f=fopen(file,"r")) == NULL)
5719 return -1;
5720
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005721 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005722 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005723 char *end;
5724 char *args[MAX_LINE_ARGS + 1];
5725 char *line = thisline;
5726
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 linenum++;
5728
5729 end = line + strlen(line);
5730
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005731 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5732 /* Check if we reached the limit and the last char is not \n.
5733 * Watch out for the last line without the terminating '\n'!
5734 */
5735 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005736 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005738 }
5739
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005741 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 line++;
5743
5744 arg = 0;
5745 args[arg] = line;
5746
5747 while (*line && arg < MAX_LINE_ARGS) {
5748 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5749 * C equivalent value. Other combinations left unchanged (eg: \1).
5750 */
5751 if (*line == '\\') {
5752 int skip = 0;
5753 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5754 *line = line[1];
5755 skip = 1;
5756 }
5757 else if (line[1] == 'r') {
5758 *line = '\r';
5759 skip = 1;
5760 }
5761 else if (line[1] == 'n') {
5762 *line = '\n';
5763 skip = 1;
5764 }
5765 else if (line[1] == 't') {
5766 *line = '\t';
5767 skip = 1;
5768 }
5769 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 unsigned char hex1, hex2;
5772 hex1 = toupper(line[2]) - '0';
5773 hex2 = toupper(line[3]) - '0';
5774 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5775 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5776 *line = (hex1<<4) + hex2;
5777 skip = 3;
5778 }
5779 else {
5780 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005781 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
5783 }
5784 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005785 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 end -= skip;
5787 }
5788 line++;
5789 }
5790 else if (*line == '#' || *line == '\n' || *line == '\r') {
5791 /* end of string, end of loop */
5792 *line = 0;
5793 break;
5794 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005795 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005797 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005798 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 line++;
5800 args[++arg] = line;
5801 }
5802 else {
5803 line++;
5804 }
5805 }
5806
5807 /* empty line */
5808 if (!**args)
5809 continue;
5810
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005811 if (*line) {
5812 /* we had to stop due to too many args.
5813 * Let's terminate the string, print the offending part then cut the
5814 * last arg.
5815 */
5816 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5817 line++;
5818 *line = '\0';
5819
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005820 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005821 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 args[arg] = line;
5824 }
5825
Willy Tarreau540abe42007-05-02 20:50:16 +02005826 /* zero out remaining args and ensure that at least one entry
5827 * is zeroed out.
5828 */
5829 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830 args[arg] = line;
5831 }
5832
Willy Tarreau3842f002009-06-14 11:39:52 +02005833 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005834 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005835 char *tmp;
5836
Willy Tarreau3842f002009-06-14 11:39:52 +02005837 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005838 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005839 for (arg=0; *args[arg+1]; arg++)
5840 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005841 *tmp = '\0'; // fix the next arg to \0
5842 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005843 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005844 else if (!strcmp(args[0], "default")) {
5845 kwm = KWM_DEF;
5846 for (arg=0; *args[arg+1]; arg++)
5847 args[arg] = args[arg+1]; // shift args after inversion
5848 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005849
William Lallemand0f99e342011-10-12 17:50:54 +02005850 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5851 strcmp(args[0], "log") != 0) {
5852 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005853 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005854 }
5855
Willy Tarreau977b8e42006-12-29 14:19:17 +01005856 if (!strcmp(args[0], "listen") ||
5857 !strcmp(args[0], "frontend") ||
5858 !strcmp(args[0], "backend") ||
5859 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005860 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005862 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005863 cursection = strdup(args[0]);
5864 }
5865 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005867 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005868 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005869 }
5870 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005871 confsect = CFG_USERLIST;
5872 free(cursection);
5873 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005874 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005875 else if (!strcmp(args[0], "peers")) {
5876 confsect = CFG_PEERS;
5877 free(cursection);
5878 cursection = strdup(args[0]);
5879 }
5880
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 /* else it's a section keyword */
5882
5883 switch (confsect) {
5884 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 break;
5887 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005888 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005890 case CFG_USERLIST:
5891 err_code |= cfg_parse_users(file, linenum, args, kwm);
5892 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005893 case CFG_PEERS:
5894 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5895 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005897 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005898 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005900
5901 if (err_code & ERR_ABORT)
5902 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005904 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005905 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005907 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005908}
5909
Willy Tarreaubb925012009-07-23 13:36:36 +02005910/*
5911 * Returns the error code, 0 if OK, or any combination of :
5912 * - ERR_ABORT: must abort ASAP
5913 * - ERR_FATAL: we can continue parsing but not start the service
5914 * - ERR_WARN: a warning has been emitted
5915 * - ERR_ALERT: an alert has been emitted
5916 * Only the two first ones can stop processing, the two others are just
5917 * indicators.
5918 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005919int check_config_validity()
5920{
5921 int cfgerr = 0;
5922 struct proxy *curproxy = NULL;
5923 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005924 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005925 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005926 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005927 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005929 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 /*
5931 * Now, check for the integrity of all that we have collected.
5932 */
5933
5934 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005935 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936
Willy Tarreau193b8c62012-11-22 00:17:38 +01005937 if (!global.tune.max_http_hdr)
5938 global.tune.max_http_hdr = MAX_HTTP_HDR;
5939
5940 if (!global.tune.cookie_len)
5941 global.tune.cookie_len = CAPTURE_LEN;
5942
5943 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5944
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005945 /* first, we will invert the proxy list order */
5946 curproxy = NULL;
5947 while (proxy) {
5948 struct proxy *next;
5949
5950 next = proxy->next;
5951 proxy->next = curproxy;
5952 curproxy = proxy;
5953 if (!next)
5954 break;
5955 proxy = next;
5956 }
5957
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005959 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005960 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005961 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005962 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005963 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005964 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005965 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005966
Willy Tarreau050536d2012-10-04 08:47:34 +02005967 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005968 /* proxy ID not set, use automatic numbering with first
5969 * spare entry starting with next_pxid.
5970 */
5971 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5972 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5973 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005974 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005975 next_pxid++;
5976
Willy Tarreau55ea7572007-06-17 19:56:27 +02005977
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005979 /* ensure we don't keep listeners uselessly bound */
5980 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 curproxy = curproxy->next;
5982 continue;
5983 }
5984
Willy Tarreau16a21472012-11-19 12:39:59 +01005985 /* number of processes this proxy is bound to */
5986 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5987
Willy Tarreauff01a212009-03-15 13:46:16 +01005988 switch (curproxy->mode) {
5989 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005990 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005991 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005992 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5993 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005994 cfgerr++;
5995 }
5996
5997 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005998 Warning("config : servers will be ignored for %s '%s'.\n",
5999 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006000 break;
6001
6002 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006003 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006004 break;
6005
6006 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006007 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006008 break;
6009 }
6010
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006011 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006012 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006013 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006014 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6015 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006016 cfgerr++;
6017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006018#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006019 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006020 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6021 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006022 cfgerr++;
6023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006025 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006026 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6027 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006028 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006029 }
6030 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006031 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006032 /* If no LB algo is set in a backend, and we're not in
6033 * transparent mode, dispatch mode nor proxy mode, we
6034 * want to use balance roundrobin by default.
6035 */
6036 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6037 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038 }
6039 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006040
Willy Tarreau1620ec32011-08-06 17:05:02 +02006041 if (curproxy->options & PR_O_DISPATCH)
6042 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6043 else if (curproxy->options & PR_O_HTTP_PROXY)
6044 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6045 else if (curproxy->options & PR_O_TRANSP)
6046 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006047
Willy Tarreau1620ec32011-08-06 17:05:02 +02006048 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6049 if (curproxy->options & PR_O_DISABLE404) {
6050 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6051 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6052 err_code |= ERR_WARN;
6053 curproxy->options &= ~PR_O_DISABLE404;
6054 }
6055 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6056 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6057 "send-state", proxy_type_str(curproxy), curproxy->id);
6058 err_code |= ERR_WARN;
6059 curproxy->options &= ~PR_O2_CHK_SNDST;
6060 }
Willy Tarreauef781042010-01-27 11:53:01 +01006061 }
6062
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006063 /* if a default backend was specified, let's find it */
6064 if (curproxy->defbe.name) {
6065 struct proxy *target;
6066
Alex Williams96532db2009-11-01 21:27:13 -05006067 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006068 if (!target) {
6069 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6070 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006071 cfgerr++;
6072 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006073 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6074 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006075 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006076 } else {
6077 free(curproxy->defbe.name);
6078 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006079 /* we force the backend to be present on at least all of
6080 * the frontend's processes.
6081 */
6082 target->bind_proc = curproxy->bind_proc ?
6083 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006084
6085 /* Emit a warning if this proxy also has some servers */
6086 if (curproxy->srv) {
6087 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6088 curproxy->id);
6089 err_code |= ERR_WARN;
6090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092 }
6093
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006094 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006095 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6096 /* map jump target for ACT_SETBE in req_rep chain */
6097 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006098 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006099 struct proxy *target;
6100
Willy Tarreaua496b602006-12-17 23:15:24 +01006101 if (exp->action != ACT_SETBE)
6102 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006103
Alex Williams96532db2009-11-01 21:27:13 -05006104 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006105 if (!target) {
6106 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6107 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006108 cfgerr++;
6109 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006110 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6111 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006112 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006113 } else {
6114 free((void *)exp->replace);
6115 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006116 /* we force the backend to be present on at least all of
6117 * the frontend's processes.
6118 */
6119 target->bind_proc = curproxy->bind_proc ?
6120 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006121 }
6122 }
6123 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006124
6125 /* find the target proxy for 'use_backend' rules */
6126 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006127 struct proxy *target;
6128
Alex Williams96532db2009-11-01 21:27:13 -05006129 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006130
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006131 if (!target) {
6132 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6133 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006134 cfgerr++;
6135 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006136 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6137 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006138 cfgerr++;
6139 } else {
6140 free((void *)rule->be.name);
6141 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006142 /* we force the backend to be present on at least all of
6143 * the frontend's processes.
6144 */
6145 target->bind_proc = curproxy->bind_proc ?
6146 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006147 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006148 }
6149
6150 /* find the target proxy for 'use_backend' rules */
6151 list_for_each_entry(srule, &curproxy->server_rules, list) {
6152 struct server *target = findserver(curproxy, srule->srv.name);
6153
6154 if (!target) {
6155 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6156 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6157 cfgerr++;
6158 continue;
6159 }
6160 free((void *)srule->srv.name);
6161 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006162 }
6163
Emeric Brunb982a3d2010-01-04 15:45:53 +01006164 /* find the target table for 'stick' rules */
6165 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6166 struct proxy *target;
6167
Emeric Brun1d33b292010-01-04 15:47:17 +01006168 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6169 if (mrule->flags & STK_IS_STORE)
6170 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6171
Emeric Brunb982a3d2010-01-04 15:45:53 +01006172 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006173 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006174 else
6175 target = curproxy;
6176
6177 if (!target) {
6178 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6179 curproxy->id, mrule->table.name);
6180 cfgerr++;
6181 }
6182 else if (target->table.size == 0) {
6183 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6184 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6185 cfgerr++;
6186 }
Willy Tarreau12785782012-04-27 21:37:17 +02006187 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6188 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006189 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6190 cfgerr++;
6191 }
6192 else {
6193 free((void *)mrule->table.name);
6194 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006195 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006196 }
6197 }
6198
6199 /* find the target table for 'store response' rules */
6200 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6201 struct proxy *target;
6202
Emeric Brun1d33b292010-01-04 15:47:17 +01006203 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6204
Emeric Brunb982a3d2010-01-04 15:45:53 +01006205 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006206 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006207 else
6208 target = curproxy;
6209
6210 if (!target) {
6211 Alert("Proxy '%s': unable to find store table '%s'.\n",
6212 curproxy->id, mrule->table.name);
6213 cfgerr++;
6214 }
6215 else if (target->table.size == 0) {
6216 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6217 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6218 cfgerr++;
6219 }
Willy Tarreau12785782012-04-27 21:37:17 +02006220 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6221 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006222 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6223 cfgerr++;
6224 }
6225 else {
6226 free((void *)mrule->table.name);
6227 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006228 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006229 }
6230 }
6231
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006232 /* find the target table for 'tcp-request' layer 4 rules */
6233 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6234 struct proxy *target;
6235
Willy Tarreau56123282010-08-06 19:06:56 +02006236 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006237 continue;
6238
6239 if (trule->act_prm.trk_ctr.table.n)
6240 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6241 else
6242 target = curproxy;
6243
6244 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006245 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6246 curproxy->id, trule->act_prm.trk_ctr.table.n,
6247 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006248 cfgerr++;
6249 }
6250 else if (target->table.size == 0) {
6251 Alert("Proxy '%s': table '%s' used but not configured.\n",
6252 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6253 cfgerr++;
6254 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006255 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6256 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6257 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6258 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6259 cfgerr++;
6260 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006261 else {
6262 free(trule->act_prm.trk_ctr.table.n);
6263 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006264 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006265 * to pass a list of counters to track and allocate them right here using
6266 * stktable_alloc_data_type().
6267 */
6268 }
6269 }
6270
Willy Tarreaud1f96522010-08-03 19:34:32 +02006271 /* find the target table for 'tcp-request' layer 6 rules */
6272 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6273 struct proxy *target;
6274
Willy Tarreau56123282010-08-06 19:06:56 +02006275 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006276 continue;
6277
6278 if (trule->act_prm.trk_ctr.table.n)
6279 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6280 else
6281 target = curproxy;
6282
6283 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006284 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6285 curproxy->id, trule->act_prm.trk_ctr.table.n,
6286 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006287 cfgerr++;
6288 }
6289 else if (target->table.size == 0) {
6290 Alert("Proxy '%s': table '%s' used but not configured.\n",
6291 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6292 cfgerr++;
6293 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006294 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6295 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6296 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6297 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6298 cfgerr++;
6299 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006300 else {
6301 free(trule->act_prm.trk_ctr.table.n);
6302 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006303 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006304 * to pass a list of counters to track and allocate them right here using
6305 * stktable_alloc_data_type().
6306 */
6307 }
6308 }
6309
Emeric Brun32da3c42010-09-23 18:39:19 +02006310 if (curproxy->table.peers.name) {
6311 struct peers *curpeers = peers;
6312
6313 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6314 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6315 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006316 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006317 break;
6318 }
6319 }
6320
6321 if (!curpeers) {
6322 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6323 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006324 free((void *)curproxy->table.peers.name);
6325 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006326 cfgerr++;
6327 }
6328 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006329 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6330 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006331 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006332 cfgerr++;
6333 }
6334 }
6335
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006336 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006337 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006338 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6339 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6340 "proxy", curproxy->id);
6341 cfgerr++;
6342 goto out_uri_auth_compat;
6343 }
6344
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006345 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006346 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006347 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006348 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006349
Willy Tarreau95fa4692010-02-01 13:05:50 +01006350 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6351 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006352
6353 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006354 uri_auth_compat_req[i++] = "realm";
6355 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6356 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006357
Willy Tarreau95fa4692010-02-01 13:05:50 +01006358 uri_auth_compat_req[i++] = "unless";
6359 uri_auth_compat_req[i++] = "{";
6360 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6361 uri_auth_compat_req[i++] = "}";
6362 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006363
Willy Tarreauff011f22011-01-06 17:51:27 +01006364 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6365 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006366 cfgerr++;
6367 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006368 }
6369
Willy Tarreauff011f22011-01-06 17:51:27 +01006370 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006371
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006372 if (curproxy->uri_auth->auth_realm) {
6373 free(curproxy->uri_auth->auth_realm);
6374 curproxy->uri_auth->auth_realm = NULL;
6375 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006376
6377 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006378 }
6379out_uri_auth_compat:
6380
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006381 cfgerr += acl_find_targets(curproxy);
6382
Willy Tarreau2738a142006-07-08 17:28:09 +02006383 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006384 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006385 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006386 (!curproxy->timeout.connect ||
6387 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006388 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006389 " | While not properly invalid, you will certainly encounter various problems\n"
6390 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006391 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006392 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006393 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006394 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006395
Willy Tarreau1fa31262007-12-03 00:36:16 +01006396 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6397 * We must still support older configurations, so let's find out whether those
6398 * parameters have been set or must be copied from contimeouts.
6399 */
6400 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006401 if (!curproxy->timeout.tarpit ||
6402 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006403 /* tarpit timeout not set. We search in the following order:
6404 * default.tarpit, curr.connect, default.connect.
6405 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006406 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006407 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006408 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006409 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006410 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006411 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006412 }
6413 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006414 (!curproxy->timeout.queue ||
6415 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006416 /* queue timeout not set. We search in the following order:
6417 * default.queue, curr.connect, default.connect.
6418 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006419 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006420 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006421 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006422 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006423 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006424 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006425 }
6426 }
6427
Willy Tarreau1620ec32011-08-06 17:05:02 +02006428 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006429 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6430 curproxy->check_req = (char *)malloc(curproxy->check_len);
6431 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006432 }
6433
Willy Tarreau193b8c62012-11-22 00:17:38 +01006434 /* ensure that cookie capture length is not too large */
6435 if (curproxy->capture_len >= global.tune.cookie_len) {
6436 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6437 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6438 err_code |= ERR_WARN;
6439 curproxy->capture_len = global.tune.cookie_len - 1;
6440 }
6441
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006442 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006443 if (curproxy->nb_req_cap) {
6444 if (curproxy->mode == PR_MODE_HTTP) {
6445 curproxy->req_cap_pool = create_pool("ptrcap",
6446 curproxy->nb_req_cap * sizeof(char *),
6447 MEM_F_SHARED);
6448 } else {
6449 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6450 proxy_type_str(curproxy), curproxy->id);
6451 err_code |= ERR_WARN;
6452 curproxy->to_log &= ~LW_REQHDR;
6453 curproxy->nb_req_cap = 0;
6454 }
6455 }
6456
6457 if (curproxy->nb_rsp_cap) {
6458 if (curproxy->mode == PR_MODE_HTTP) {
6459 curproxy->rsp_cap_pool = create_pool("ptrcap",
6460 curproxy->nb_rsp_cap * sizeof(char *),
6461 MEM_F_SHARED);
6462 } else {
6463 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6464 proxy_type_str(curproxy), curproxy->id);
6465 err_code |= ERR_WARN;
6466 curproxy->to_log &= ~LW_REQHDR;
6467 curproxy->nb_rsp_cap = 0;
6468 }
6469 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006470
Willy Tarreau196729e2012-05-31 19:30:26 +02006471 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006472 if (!(curproxy->cap & PR_CAP_FE)) {
6473 if (curproxy->logformat_string != default_http_log_format &&
6474 curproxy->logformat_string != default_tcp_log_format &&
6475 curproxy->logformat_string != clf_http_log_format)
6476 free(curproxy->logformat_string);
6477 curproxy->logformat_string = NULL;
6478 }
6479
Willy Tarreau196729e2012-05-31 19:30:26 +02006480 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006481 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006482
6483 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006484 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006485
Willy Tarreaubaaee002006-06-26 02:48:02 +02006486 /* first, we will invert the servers list order */
6487 newsrv = NULL;
6488 while (curproxy->srv) {
6489 struct server *next;
6490
6491 next = curproxy->srv->next;
6492 curproxy->srv->next = newsrv;
6493 newsrv = curproxy->srv;
6494 if (!next)
6495 break;
6496 curproxy->srv = next;
6497 }
6498
Willy Tarreaudd701652010-05-25 23:03:02 +02006499 /* assign automatic UIDs to servers which don't have one yet */
6500 next_id = 1;
6501 newsrv = curproxy->srv;
6502 while (newsrv != NULL) {
6503 if (!newsrv->puid) {
6504 /* server ID not set, use automatic numbering with first
6505 * spare entry starting with next_svid.
6506 */
6507 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6508 newsrv->conf.id.key = newsrv->puid = next_id;
6509 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6510 }
6511 next_id++;
6512 newsrv = newsrv->next;
6513 }
6514
Willy Tarreau20697042007-11-15 23:26:18 +01006515 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006516 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517
Willy Tarreau62c3be22012-01-20 13:12:32 +01006518 /*
6519 * If this server supports a maxconn parameter, it needs a dedicated
6520 * tasks to fill the emptied slots when a connection leaves.
6521 * Also, resolve deferred tracking dependency if needed.
6522 */
6523 newsrv = curproxy->srv;
6524 while (newsrv != NULL) {
6525 if (newsrv->minconn > newsrv->maxconn) {
6526 /* Only 'minconn' was specified, or it was higher than or equal
6527 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6528 * this will avoid further useless expensive computations.
6529 */
6530 newsrv->maxconn = newsrv->minconn;
6531 } else if (newsrv->maxconn && !newsrv->minconn) {
6532 /* minconn was not specified, so we set it to maxconn */
6533 newsrv->minconn = newsrv->maxconn;
6534 }
6535
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006536#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006537 if (newsrv->use_ssl || newsrv->check.use_ssl)
6538 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006539#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006540
Willy Tarreau62c3be22012-01-20 13:12:32 +01006541 if (newsrv->trackit) {
6542 struct proxy *px;
6543 struct server *srv;
6544 char *pname, *sname;
6545
6546 pname = newsrv->trackit;
6547 sname = strrchr(pname, '/');
6548
6549 if (sname)
6550 *sname++ = '\0';
6551 else {
6552 sname = pname;
6553 pname = NULL;
6554 }
6555
6556 if (pname) {
6557 px = findproxy(pname, PR_CAP_BE);
6558 if (!px) {
6559 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6560 proxy_type_str(curproxy), curproxy->id,
6561 newsrv->id, pname);
6562 cfgerr++;
6563 goto next_srv;
6564 }
6565 } else
6566 px = curproxy;
6567
6568 srv = findserver(px, sname);
6569 if (!srv) {
6570 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6571 proxy_type_str(curproxy), curproxy->id,
6572 newsrv->id, sname);
6573 cfgerr++;
6574 goto next_srv;
6575 }
6576
6577 if (!(srv->state & SRV_CHECKED)) {
6578 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6579 "tracking as it does not have checks enabled.\n",
6580 proxy_type_str(curproxy), curproxy->id,
6581 newsrv->id, px->id, srv->id);
6582 cfgerr++;
6583 goto next_srv;
6584 }
6585
6586 if (curproxy != px &&
6587 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6588 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6589 "tracking: disable-on-404 option inconsistency.\n",
6590 proxy_type_str(curproxy), curproxy->id,
6591 newsrv->id, px->id, srv->id);
6592 cfgerr++;
6593 goto next_srv;
6594 }
6595
6596 /* if the other server is forced disabled, we have to do the same here */
6597 if (srv->state & SRV_MAINTAIN) {
6598 newsrv->state |= SRV_MAINTAIN;
6599 newsrv->state &= ~SRV_RUNNING;
6600 newsrv->health = 0;
6601 }
6602
6603 newsrv->track = srv;
6604 newsrv->tracknext = srv->tracknext;
6605 srv->tracknext = newsrv;
6606
6607 free(newsrv->trackit);
6608 newsrv->trackit = NULL;
6609 }
6610 next_srv:
6611 newsrv = newsrv->next;
6612 }
6613
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006614 /* We have to initialize the server lookup mechanism depending
6615 * on what LB algorithm was choosen.
6616 */
6617
6618 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6619 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6620 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006621 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6622 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6623 init_server_map(curproxy);
6624 } else {
6625 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6626 fwrr_init_server_groups(curproxy);
6627 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006628 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006629
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006630 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006631 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6632 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6633 fwlc_init_server_tree(curproxy);
6634 } else {
6635 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6636 fas_init_server_tree(curproxy);
6637 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006638 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006639
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006640 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006641 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6642 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6643 chash_init_server_tree(curproxy);
6644 } else {
6645 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6646 init_server_map(curproxy);
6647 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006648 break;
6649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006650
6651 if (curproxy->options & PR_O_LOGASAP)
6652 curproxy->to_log &= ~LW_BYTES;
6653
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006654 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006655 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006656 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6657 proxy_type_str(curproxy), curproxy->id);
6658 err_code |= ERR_WARN;
6659 }
6660
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006661 if (curproxy->mode != PR_MODE_HTTP) {
6662 int optnum;
6663
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006664 if (curproxy->uri_auth) {
6665 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6666 proxy_type_str(curproxy), curproxy->id);
6667 err_code |= ERR_WARN;
6668 curproxy->uri_auth = NULL;
6669 }
6670
Willy Tarreau87cf5142011-08-19 22:57:24 +02006671 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006672 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6673 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6674 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006675 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006676 }
6677
6678 if (curproxy->options & PR_O_ORGTO) {
6679 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6680 "originalto", proxy_type_str(curproxy), curproxy->id);
6681 err_code |= ERR_WARN;
6682 curproxy->options &= ~PR_O_ORGTO;
6683 }
6684
6685 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6686 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6687 (curproxy->cap & cfg_opts[optnum].cap) &&
6688 (curproxy->options & cfg_opts[optnum].val)) {
6689 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6690 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6691 err_code |= ERR_WARN;
6692 curproxy->options &= ~cfg_opts[optnum].val;
6693 }
6694 }
6695
6696 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6697 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6698 (curproxy->cap & cfg_opts2[optnum].cap) &&
6699 (curproxy->options2 & cfg_opts2[optnum].val)) {
6700 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6701 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6702 err_code |= ERR_WARN;
6703 curproxy->options2 &= ~cfg_opts2[optnum].val;
6704 }
6705 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006706
Willy Tarreauefa5f512010-03-30 20:13:29 +02006707#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006708 if (curproxy->conn_src.bind_hdr_occ) {
6709 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006710 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006711 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006712 err_code |= ERR_WARN;
6713 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006714#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006715 }
6716
Willy Tarreaubaaee002006-06-26 02:48:02 +02006717 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006718 * ensure that we're not cross-dressing a TCP server into HTTP.
6719 */
6720 newsrv = curproxy->srv;
6721 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006722 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006723 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6724 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006725 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006726 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006727
Willy Tarreau0cec3312011-10-31 13:49:26 +01006728 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6729 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6730 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6731 err_code |= ERR_WARN;
6732 }
6733
Willy Tarreauefa5f512010-03-30 20:13:29 +02006734#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006735 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6736 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006737 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006738 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006739 err_code |= ERR_WARN;
6740 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006741#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006742 newsrv = newsrv->next;
6743 }
6744
Willy Tarreauc1a21672009-08-16 22:37:44 +02006745 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006746 if (!curproxy->accept)
6747 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006748
Willy Tarreauc1a21672009-08-16 22:37:44 +02006749 if (curproxy->tcp_req.inspect_delay ||
6750 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006751 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006752
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006753 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006754 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006755 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006756 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006757
6758 /* both TCP and HTTP must check switching rules */
6759 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6760 }
6761
6762 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006763 if (curproxy->tcp_req.inspect_delay ||
6764 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6765 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6766
Emeric Brun97679e72010-09-23 17:56:44 +02006767 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6768 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6769
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006770 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006771 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006772 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006773 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006774
6775 /* If the backend does requires RDP cookie persistence, we have to
6776 * enable the corresponding analyser.
6777 */
6778 if (curproxy->options2 & PR_O2_RDPC_PRST)
6779 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6780 }
6781
Emeric Brunc52962f2012-11-15 18:28:02 +01006782#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006783 /* Configure SSL for each bind line.
6784 * Note: if configuration fails at some point, the ->ctx member
6785 * remains NULL so that listeners can later detach.
6786 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006787 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006788 if (!bind_conf->is_ssl) {
6789 if (bind_conf->default_ctx) {
6790 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6791 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6792 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006793 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006794 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006795 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006796 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006797 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006798 cfgerr++;
6799 continue;
6800 }
6801
Emeric Brun4b3091e2012-09-24 15:48:52 +02006802 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006803 Alert("Unable to allocate SSL session cache.\n");
6804 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006805 continue;
6806 }
6807
Emeric Brunfc0421f2012-09-07 17:30:07 +02006808 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006809 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006810 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006811#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006812
Willy Tarreaue6b98942007-10-29 01:09:36 +01006813 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006814 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006815 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006816 if (!listener->luid) {
6817 /* listener ID not set, use automatic numbering with first
6818 * spare entry starting with next_luid.
6819 */
6820 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6821 listener->conf.id.key = listener->luid = next_id;
6822 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006823 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006824 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006825
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006826 /* enable separate counters */
6827 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6828 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006829 if (!listener->name)
6830 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006831 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006832
Willy Tarreaue6b98942007-10-29 01:09:36 +01006833 if (curproxy->options & PR_O_TCP_NOLING)
6834 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006835 if (!listener->maxconn)
6836 listener->maxconn = curproxy->maxconn;
6837 if (!listener->backlog)
6838 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006839 if (!listener->maxaccept)
6840 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6841
6842 /* we want to have an optimal behaviour on single process mode to
6843 * maximize the work at once, but in multi-process we want to keep
6844 * some fairness between processes, so we target half of the max
6845 * number of events to be balanced over all the processes the proxy
6846 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6847 * used to disable the limit.
6848 */
6849 if (listener->maxaccept > 0) {
6850 if (nbproc > 1)
6851 listener->maxaccept = (listener->maxaccept + 1) / 2;
6852 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6853 }
6854
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006855 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006856 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006857 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006858 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006859
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006860 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6861 listener->options |= LI_O_TCP_RULES;
6862
Willy Tarreaude3041d2010-05-31 10:56:17 +02006863 if (curproxy->mon_mask.s_addr)
6864 listener->options |= LI_O_CHK_MONNET;
6865
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006866 /* smart accept mode is automatic in HTTP mode */
6867 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006868 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006869 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6870 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006871 }
6872
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006873 /* Release unused SSL configs */
6874 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6875 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006876 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006877#ifdef USE_OPENSSL
6878 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006879 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006880 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006881 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006882 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006883#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006884 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006885
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006886 /* Check multi-process mode compatibility for the current proxy */
6887 if (global.nbproc > 1) {
6888 int nbproc = 0;
6889 if (curproxy->bind_proc) {
6890 int proc;
6891 for (proc = 0; proc < global.nbproc; proc++) {
6892 if (curproxy->bind_proc & (1 << proc)) {
6893 nbproc++;
6894 }
6895 }
6896 } else {
6897 nbproc = global.nbproc;
6898 }
6899 if (curproxy->table.peers.name) {
6900 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6901 curproxy->id);
6902 cfgerr++;
6903 }
6904 if (nbproc > 1) {
6905 if (curproxy->uri_auth) {
6906 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6907 curproxy->id);
6908 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6909 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6910 curproxy->id);
6911 }
6912 }
6913 if (curproxy->appsession_name) {
6914 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6915 curproxy->id);
6916 }
6917 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6918 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6919 curproxy->id);
6920 }
6921 }
6922 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006923
6924 /* create the task associated with the proxy */
6925 curproxy->task = task_new();
6926 if (curproxy->task) {
6927 curproxy->task->context = curproxy;
6928 curproxy->task->process = manage_proxy;
6929 /* no need to queue, it will be done automatically if some
6930 * listener gets limited.
6931 */
6932 curproxy->task->expire = TICK_ETERNITY;
6933 } else {
6934 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6935 curproxy->id);
6936 cfgerr++;
6937 }
6938
Willy Tarreaubaaee002006-06-26 02:48:02 +02006939 curproxy = curproxy->next;
6940 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006941
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006942 /* Check multi-process mode compatibility */
6943 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006944 if (global.stats_fe && !global.stats_fe->bind_proc) {
6945 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006946 }
6947 }
6948
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006949 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6950 struct auth_users *curuser;
6951 int g;
6952
6953 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6954 unsigned int group_mask = 0;
6955 char *group = NULL;
6956
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006957 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006958 continue;
6959
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006960 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006961
6962 for (g = 0; g < curuserlist->grpcnt; g++)
6963 if (!strcmp(curuserlist->groups[g], group))
6964 break;
6965
6966 if (g == curuserlist->grpcnt) {
6967 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6968 curuserlist->name, group, curuser->user);
6969 err_code |= ERR_ALERT | ERR_FATAL;
6970 goto out;
6971 }
6972
6973 group_mask |= (1 << g);
6974 }
6975
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006976 free(curuser->u.groups);
6977 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006978 }
6979
6980 for (g = 0; g < curuserlist->grpcnt; g++) {
6981 char *user = NULL;
6982
6983 if (!curuserlist->groupusers[g])
6984 continue;
6985
6986 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6987 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6988 if (!strcmp(curuser->user, user))
6989 break;
6990
6991 if (!curuser) {
6992 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6993 curuserlist->name, user, curuserlist->groups[g]);
6994 err_code |= ERR_ALERT | ERR_FATAL;
6995 goto out;
6996 }
6997
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006998 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006999 }
7000
7001 free(curuserlist->groupusers[g]);
7002 }
7003
7004 free(curuserlist->groupusers);
7005
7006#ifdef DEBUG_AUTH
7007 for (g = 0; g < curuserlist->grpcnt; g++) {
7008 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7009
7010 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007011 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007012 fprintf(stderr, " %s", curuser->user);
7013 }
7014
7015 fprintf(stderr, "\n");
7016 }
7017#endif
7018
Willy Tarreaufbb78422011-06-05 15:38:35 +02007019 }
7020
7021 /* automatically compute fullconn if not set. We must not do it in the
7022 * loop above because cross-references are not yet fully resolved.
7023 */
7024 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7025 /* If <fullconn> is not set, let's set it to 10% of the sum of
7026 * the possible incoming frontend's maxconns.
7027 */
7028 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7029 struct proxy *fe;
7030 int total = 0;
7031
7032 /* sum up the number of maxconns of frontends which
7033 * reference this backend at least once or which are
7034 * the same one ('listen').
7035 */
7036 for (fe = proxy; fe; fe = fe->next) {
7037 struct switching_rule *rule;
7038 struct hdr_exp *exp;
7039 int found = 0;
7040
7041 if (!(fe->cap & PR_CAP_FE))
7042 continue;
7043
7044 if (fe == curproxy) /* we're on a "listen" instance */
7045 found = 1;
7046
7047 if (fe->defbe.be == curproxy) /* "default_backend" */
7048 found = 1;
7049
7050 /* check if a "use_backend" rule matches */
7051 if (!found) {
7052 list_for_each_entry(rule, &fe->switching_rules, list) {
7053 if (rule->be.backend == curproxy) {
7054 found = 1;
7055 break;
7056 }
7057 }
7058 }
7059
7060 /* check if a "reqsetbe" rule matches */
7061 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7062 if (exp->action == ACT_SETBE &&
7063 (struct proxy *)exp->replace == curproxy) {
7064 found = 1;
7065 break;
7066 }
7067 }
7068
7069 /* now we've checked all possible ways to reference a backend
7070 * from a frontend.
7071 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007072 if (!found)
7073 continue;
7074 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007075 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007076 /* we have the sum of the maxconns in <total>. We only
7077 * keep 10% of that sum to set the default fullconn, with
7078 * a hard minimum of 1 (to avoid a divide by zero).
7079 */
7080 curproxy->fullconn = (total + 9) / 10;
7081 if (!curproxy->fullconn)
7082 curproxy->fullconn = 1;
7083 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007084 }
7085
Willy Tarreau056f5682010-06-06 15:51:11 +02007086 /* initialize stick-tables on backend capable proxies. This must not
7087 * be done earlier because the data size may be discovered while parsing
7088 * other proxies.
7089 */
7090 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007091 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007092
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007093 /*
7094 * Recount currently required checks.
7095 */
7096
7097 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7098 int optnum;
7099
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007100 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7101 if (curproxy->options & cfg_opts[optnum].val)
7102 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007103
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007104 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7105 if (curproxy->options2 & cfg_opts2[optnum].val)
7106 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007107 }
7108
Willy Tarreau122541c2011-09-07 21:24:49 +02007109 if (peers) {
7110 struct peers *curpeers = peers, **last;
7111 struct peer *p, *pb;
7112
7113 /* Remove all peers sections which don't have a valid listener.
7114 * This can happen when a peers section is never referenced and
7115 * does not contain a local peer.
7116 */
7117 last = &peers;
7118 while (*last) {
7119 curpeers = *last;
7120 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007121 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007122 last = &curpeers->next;
7123 continue;
7124 }
7125
7126 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7127 curpeers->id, localpeer);
7128
7129 p = curpeers->remote;
7130 while (p) {
7131 pb = p->next;
7132 free(p->id);
7133 free(p);
7134 p = pb;
7135 }
7136
7137 /* Destroy and unlink this curpeers section.
7138 * Note: curpeers is backed up into *last.
7139 */
7140 free(curpeers->id);
7141 curpeers = curpeers->next;
7142 free(*last);
7143 *last = curpeers;
7144 }
7145 }
7146
Willy Tarreau34eb6712011-10-24 18:15:04 +02007147 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007148 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007149 MEM_F_SHARED);
7150
Willy Tarreaubb925012009-07-23 13:36:36 +02007151 if (cfgerr > 0)
7152 err_code |= ERR_ALERT | ERR_FATAL;
7153 out:
7154 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007155}
7156
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007157/*
7158 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7159 * parsing sessions.
7160 */
7161void cfg_register_keywords(struct cfg_kw_list *kwl)
7162{
7163 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7164}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007165
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007166/*
7167 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7168 */
7169void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7170{
7171 LIST_DEL(&kwl->list);
7172 LIST_INIT(&kwl->list);
7173}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007174
7175/*
7176 * Local variables:
7177 * c-indent-level: 8
7178 * c-basic-offset: 8
7179 * End:
7180 */