blob: 1a2fc8ab644835fd522266fcd6d11219e6272326 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy 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 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200599#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200600 else if (!strcmp(args[0], "tune.bufsize")) {
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.bufsize = atol(args[1]);
607 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
608 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100609 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100621 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
622 if (global.tune.client_rcvbuf != 0) {
623 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT;
625 goto out;
626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.tune.client_rcvbuf = atol(args[1]);
633 }
634 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
635 if (global.tune.server_rcvbuf != 0) {
636 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT;
638 goto out;
639 }
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.server_rcvbuf = atol(args[1]);
646 }
647 else if (!strcmp(args[0], "tune.sndbuf.client")) {
648 if (global.tune.client_sndbuf != 0) {
649 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT;
651 goto out;
652 }
653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.client_sndbuf = atol(args[1]);
659 }
660 else if (!strcmp(args[0], "tune.sndbuf.server")) {
661 if (global.tune.server_sndbuf != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT;
664 goto out;
665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.server_sndbuf = atol(args[1]);
672 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200673 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
680 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100681 else if (!strcmp(args[0], "tune.http.cookielen")) {
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.cookie_len = atol(args[1]) + 1;
688 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200689 else if (!strcmp(args[0], "tune.http.maxhdr")) {
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.max_http_hdr = atol(args[1]);
696 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100697 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
698#ifdef USE_ZLIB
699 if (*args[1]) {
700 global.tune.zlibmemlevel = atoi(args[1]);
701 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
702 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
703 file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 } else {
708 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713#else
714 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717#endif
718 }
719 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
720#ifdef USE_ZLIB
721 if (*args[1]) {
722 global.tune.zlibwindowsize = atoi(args[1]);
723 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
724 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
725 file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729 } else {
730 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
731 file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735#else
736 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739#endif
740 }
William Lallemandf3747832012-11-09 12:33:10 +0100741 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
742 if (*args[1]) {
743 global.tune.comp_maxlevel = atoi(args[1]);
744 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
745 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
746 file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750 } else {
751 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 else if (!strcmp(args[0], "uid")) {
758 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
768 global.uid = atol(args[1]);
769 }
770 else if (!strcmp(args[0], "gid")) {
771 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.gid = atol(args[1]);
782 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200783 /* user/group name handling */
784 else if (!strcmp(args[0], "user")) {
785 struct passwd *ha_user;
786 if (global.uid != 0) {
787 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT;
789 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200790 }
791 errno = 0;
792 ha_user = getpwnam(args[1]);
793 if (ha_user != NULL) {
794 global.uid = (int)ha_user->pw_uid;
795 }
796 else {
797 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 +0200798 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200799 }
800 }
801 else if (!strcmp(args[0], "group")) {
802 struct group *ha_group;
803 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200804 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200807 }
808 errno = 0;
809 ha_group = getgrnam(args[1]);
810 if (ha_group != NULL) {
811 global.gid = (int)ha_group->gr_gid;
812 }
813 else {
814 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 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200816 }
817 }
818 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 }
825 global.nbproc = atol(args[1]);
826 }
827 else if (!strcmp(args[0], "maxconn")) {
828 if (global.maxconn != 0) {
829 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
838 global.maxconn = atol(args[1]);
839#ifdef SYSTEM_MAXCONN
840 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
841 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);
842 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845#endif /* SYSTEM_MAXCONN */
846 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200847 else if (!strcmp(args[0], "maxsslconn")) {
848#ifdef USE_OPENSSL
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 global.maxsslconn = atol(args[1]);
855#else
Emeric Brun0914df82012-10-02 18:45:42 +0200856 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200859#endif
860 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200861 else if (!strcmp(args[0], "maxconnrate")) {
862 if (global.cps_lim != 0) {
863 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT;
865 goto out;
866 }
867 if (*(args[1]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.cps_lim = atol(args[1]);
873 }
William Lallemandd85f9172012-11-09 17:05:39 +0100874 else if (!strcmp(args[0], "maxcomprate")) {
875 if (*(args[1]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 global.comp_rate_lim = atoi(args[1]) * 1024;
881 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100882 else if (!strcmp(args[0], "maxpipes")) {
883 if (global.maxpipes != 0) {
884 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100892 }
893 global.maxpipes = atol(args[1]);
894 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100895 else if (!strcmp(args[0], "maxzlibmem")) {
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
William Lallemande3a7d992012-11-20 11:25:20 +0100901 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100902 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100903 else if (!strcmp(args[0], "maxcompcpuusage")) {
904 if (*(args[1]) == 0) {
905 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100910 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100911 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915}
916
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 else if (!strcmp(args[0], "ulimit-n")) {
918 if (global.rlimit_nofile != 0) {
919 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 global.rlimit_nofile = atol(args[1]);
929 }
930 else if (!strcmp(args[0], "chroot")) {
931 if (global.chroot != NULL) {
932 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 }
941 global.chroot = strdup(args[1]);
942 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200943 else if (!strcmp(args[0], "description")) {
944 int i, len=0;
945 char *d;
946
947 if (!*args[1]) {
948 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
949 file, linenum, args[0]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953
954 for(i=1; *args[i]; i++)
955 len += strlen(args[i])+1;
956
957 if (global.desc)
958 free(global.desc);
959
960 global.desc = d = (char *)calloc(1, len);
961
962 d += sprintf(d, "%s", args[1]);
963 for(i=2; *args[i]; i++)
964 d += sprintf(d, " %s", args[i]);
965 }
966 else if (!strcmp(args[0], "node")) {
967 int i;
968 char c;
969
970 for (i=0; args[1][i]; i++) {
971 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100972 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
973 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200974 break;
975 }
976
977 if (!i || args[1][i]) {
978 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
979 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
980 file, linenum, args[0]);
981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
983 }
984
985 if (global.node)
986 free(global.node);
987
988 global.node = strdup(args[1]);
989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 else if (!strcmp(args[0], "pidfile")) {
991 if (global.pidfile != NULL) {
992 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200993 err_code |= ERR_ALERT;
994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 }
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000 }
1001 global.pidfile = strdup(args[1]);
1002 }
Emeric Bruned760922010-10-22 17:59:25 +02001003 else if (!strcmp(args[0], "unix-bind")) {
1004 int cur_arg = 1;
1005 while (*(args[cur_arg])) {
1006 if (!strcmp(args[cur_arg], "prefix")) {
1007 if (global.unix_bind.prefix != NULL) {
1008 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1009 err_code |= ERR_ALERT;
1010 cur_arg += 2;
1011 continue;
1012 }
1013
1014 if (*(args[cur_arg+1]) == 0) {
1015 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1020 cur_arg += 2;
1021 continue;
1022 }
1023
1024 if (!strcmp(args[cur_arg], "mode")) {
1025
1026 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1027 cur_arg += 2;
1028 continue;
1029 }
1030
1031 if (!strcmp(args[cur_arg], "uid")) {
1032
1033 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1034 cur_arg += 2;
1035 continue;
1036 }
1037
1038 if (!strcmp(args[cur_arg], "gid")) {
1039
1040 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1041 cur_arg += 2;
1042 continue;
1043 }
1044
1045 if (!strcmp(args[cur_arg], "user")) {
1046 struct passwd *user;
1047
1048 user = getpwnam(args[cur_arg + 1]);
1049 if (!user) {
1050 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1051 file, linenum, args[0], args[cur_arg + 1 ]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
1055
1056 global.unix_bind.ux.uid = user->pw_uid;
1057 cur_arg += 2;
1058 continue;
1059 }
1060
1061 if (!strcmp(args[cur_arg], "group")) {
1062 struct group *group;
1063
1064 group = getgrnam(args[cur_arg + 1]);
1065 if (!group) {
1066 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1067 file, linenum, args[0], args[cur_arg + 1 ]);
1068 err_code |= ERR_ALERT | ERR_FATAL;
1069 goto out;
1070 }
1071
1072 global.unix_bind.ux.gid = group->gr_gid;
1073 cur_arg += 2;
1074 continue;
1075 }
1076
Willy Tarreaub48f9582011-09-05 01:17:06 +02001077 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001078 file, linenum, args[0]);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto out;
1081 }
1082 }
William Lallemand0f99e342011-10-12 17:50:54 +02001083 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1084 /* delete previous herited or defined syslog servers */
1085 struct logsrv *back;
1086 struct logsrv *tmp;
1087
1088 if (*(args[1]) != 0) {
1089 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093
1094 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1095 LIST_DEL(&tmp->list);
1096 free(tmp);
1097 }
1098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001100 struct logsrv *logsrv;
1101
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 if (*(args[1]) == 0 || *(args[2]) == 0) {
1103 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 }
William Lallemand0f99e342011-10-12 17:50:54 +02001107
1108 logsrv = calloc(1, sizeof(struct logsrv));
1109
1110 logsrv->facility = get_log_facility(args[2]);
1111 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001112 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001113 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 }
1116
William Lallemand0f99e342011-10-12 17:50:54 +02001117 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->level = get_log_level(args[3]);
1120 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 }
1125 }
1126
William Lallemand0f99e342011-10-12 17:50:54 +02001127 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001128 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001129 logsrv->minlvl = get_log_level(args[4]);
1130 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001131 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001132 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001134 }
1135 }
1136
Robert Tsai81ae1952007-12-05 10:47:29 +01001137 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001138 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001139 if (!sk) {
1140 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001141 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001142 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001143 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001144 goto out;
1145 }
William Lallemand0f99e342011-10-12 17:50:54 +02001146 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001147 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001148 struct sockaddr_storage *sk;
1149 int port1, port2;
1150
1151 sk = str2sa_range(args[1], &port1, &port2);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001152 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001153 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n", file, linenum, args[0], args[1]);
1154 err_code |= ERR_ALERT | ERR_FATAL;
1155 free(logsrv);
1156 goto out;
1157 }
1158
1159 if (port1 != port2) {
1160 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1161 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001162 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001163 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001164 goto out;
1165 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001166
William Lallemand0f99e342011-10-12 17:50:54 +02001167 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001168 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001169 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001171
William Lallemand0f99e342011-10-12 17:50:54 +02001172 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001173 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001174 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1175 char *name;
1176 int len;
1177
1178 if (global.log_send_hostname != NULL) {
1179 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1180 err_code |= ERR_ALERT;
1181 goto out;
1182 }
1183
1184 if (*(args[1]))
1185 name = args[1];
1186 else
1187 name = hostname;
1188
1189 len = strlen(name);
1190
1191 /* We'll add a space after the name to respect the log format */
1192 free(global.log_send_hostname);
1193 global.log_send_hostname = malloc(len + 2);
1194 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1195 }
Kevinm48936af2010-12-22 16:08:21 +00001196 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1197 if (*(args[1]) == 0) {
1198 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
1201 }
1202 free(global.log_tag);
1203 global.log_tag = strdup(args[1]);
1204 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001205 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1206 if (global.spread_checks != 0) {
1207 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001208 err_code |= ERR_ALERT;
1209 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001210 }
1211 if (*(args[1]) == 0) {
1212 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001215 }
1216 global.spread_checks = atol(args[1]);
1217 if (global.spread_checks < 0 || global.spread_checks > 50) {
1218 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001219 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001222 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1223#ifdef USE_CPU_AFFINITY
1224 int cur_arg, i;
1225 unsigned int proc = 0;
1226 unsigned long cpus = 0;
1227
1228 if (strcmp(args[1], "all") == 0)
1229 proc = 0xFFFFFFFF;
1230 else if (strcmp(args[1], "odd") == 0)
1231 proc = 0x55555555;
1232 else if (strcmp(args[1], "even") == 0)
1233 proc = 0xAAAAAAAA;
1234 else {
1235 proc = atoi(args[1]);
1236 if (proc >= 1 && proc <= 32)
1237 proc = 1 << (proc - 1);
1238 }
1239
1240 if (!proc || !*args[2]) {
1241 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",
1242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 cur_arg = 2;
1248 while (*args[cur_arg]) {
1249 unsigned int low, high;
1250
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001251 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001252 char *dash = strchr(args[cur_arg], '-');
1253
1254 low = high = str2uic(args[cur_arg]);
1255 if (dash)
1256 high = str2uic(dash + 1);
1257
1258 if (high < low) {
1259 unsigned int swap = low;
1260 low = high;
1261 high = swap;
1262 }
1263
1264 if (low < 0 || high >= sizeof(long) * 8) {
1265 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1266 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270
1271 while (low <= high)
1272 cpus |= 1UL << low++;
1273 }
1274 else {
1275 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1276 file, linenum, args[0], args[cur_arg]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280 cur_arg++;
1281 }
1282 for (i = 0; i < 32; i++)
1283 if (proc & (1 << i))
1284 global.cpu_map[i] = cpus;
1285#else
1286 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289#endif
1290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001292 struct cfg_kw_list *kwl;
1293 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001294 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001295
1296 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1297 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1298 if (kwl->kw[index].section != CFG_GLOBAL)
1299 continue;
1300 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001301 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001302 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001303 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001304 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001305 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001306 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001307 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001308 err_code |= ERR_WARN;
1309 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001310 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001312 }
1313 }
1314 }
1315
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001317 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001319
Willy Tarreau058e9072009-07-20 09:30:05 +02001320 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001321 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323}
1324
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001325void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001327 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328 defproxy.mode = PR_MODE_TCP;
1329 defproxy.state = PR_STNEW;
1330 defproxy.maxconn = cfg_maxpconn;
1331 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001332
1333 defproxy.defsrv.inter = DEF_CHKINTR;
1334 defproxy.defsrv.fastinter = 0;
1335 defproxy.defsrv.downinter = 0;
1336 defproxy.defsrv.rise = DEF_RISETIME;
1337 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001338 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001339 defproxy.defsrv.maxqueue = 0;
1340 defproxy.defsrv.minconn = 0;
1341 defproxy.defsrv.maxconn = 0;
1342 defproxy.defsrv.slowstart = 0;
1343 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1344 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1345 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346}
1347
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348
1349static int create_cond_regex_rule(const char *file, int line,
1350 struct proxy *px, int dir, int action, int flags,
1351 const char *cmd, const char *reg, const char *repl,
1352 const char **cond_start)
1353{
1354 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001355 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001356 const char *err;
1357 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001359
1360 if (px == &defproxy) {
1361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto err;
1364 }
1365
1366 if (*reg == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto err;
1370 }
1371
1372 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1373 err_code |= ERR_WARN;
1374
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 if (cond_start &&
1376 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001377 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1378 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1379 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto err;
1382 }
1383 }
1384 else if (cond_start && **cond_start) {
1385 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1386 file, line, cmd, *cond_start);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto err;
1389 }
1390
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001391 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001392 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001393 else
1394 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001395
Willy Tarreauade5ec42010-01-28 19:33:49 +01001396 preg = calloc(1, sizeof(regex_t));
1397 if (!preg) {
1398 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1399 err_code = ERR_ALERT | ERR_FATAL;
1400 goto err;
1401 }
1402
1403 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1404 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1405 err_code = ERR_ALERT | ERR_FATAL;
1406 goto err;
1407 }
1408
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001409 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001410 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001411 if (repl && err) {
1412 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1413 file, line, cmd, *err);
1414 err_code |= ERR_ALERT | ERR_FATAL;
1415 goto err;
1416 }
1417
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001418 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001419 err_code |= ERR_WARN;
1420
Willy Tarreauf4068b62012-05-08 17:37:49 +02001421 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001422 return err_code;
1423 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001424 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001425 free(preg);
1426 return err_code;
1427}
1428
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001430 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001431 * Returns the error code, 0 if OK, or any combination of :
1432 * - ERR_ABORT: must abort ASAP
1433 * - ERR_FATAL: we can continue parsing but not start the service
1434 * - ERR_WARN: a warning has been emitted
1435 * - ERR_ALERT: an alert has been emitted
1436 * Only the two first ones can stop processing, the two others are just
1437 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001439int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1440{
1441 static struct peers *curpeers = NULL;
1442 struct peer *newpeer = NULL;
1443 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001444 struct bind_conf *bind_conf;
1445 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001446 int err_code = 0;
1447
1448 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1449
1450 err = invalid_char(args[1]);
1451 if (err) {
1452 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1453 file, linenum, *err, args[0], args[1]);
1454 err_code |= ERR_ALERT | ERR_FATAL;
1455 }
1456
1457 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 */
1462 if (strcmp(curpeers->id, args[1]) == 0) {
1463 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1464 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1465 err_code |= ERR_WARN;
1466 }
1467 }
1468
1469 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1470 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1471 err_code |= ERR_ALERT | ERR_ABORT;
1472 goto out;
1473 }
1474
1475 curpeers->next = peers;
1476 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001477 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001478 curpeers->conf.line = linenum;
1479 curpeers->last_change = now.tv_sec;
1480 curpeers->id = strdup(args[1]);
1481 }
1482 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001483 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001484 int port1, port2;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001485 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001486
1487 if (!*args[2]) {
1488 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1489 file, linenum, args[0]);
1490 err_code |= ERR_ALERT | ERR_FATAL;
1491 goto out;
1492 }
1493
1494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1497 file, linenum, *err, args[1]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1503 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1504 err_code |= ERR_ALERT | ERR_ABORT;
1505 goto out;
1506 }
1507
1508 /* the peers are linked backwards first */
1509 curpeers->count++;
1510 newpeer->next = curpeers->remote;
1511 curpeers->remote = newpeer;
1512 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001513 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001514 newpeer->conf.line = linenum;
1515
1516 newpeer->last_change = now.tv_sec;
1517 newpeer->id = strdup(args[1]);
1518
Willy Tarreau2aa38802013-02-20 19:20:59 +01001519 sk = str2sa_range(args[2], &port1, &port2);
1520 if (!sk) {
1521 Alert("parsing [%s:%d] : '%s %s' : unknown host in '%s'\n", file, linenum, args[0], args[1], args[2]);
1522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001525
1526 if (port1 != port2) {
1527 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1528 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532
Willy Tarreau2aa38802013-02-20 19:20:59 +01001533 if (!port1) {
1534 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1535 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001539
Emeric Brun32da3c42010-09-23 18:39:19 +02001540 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001541 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001542 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001543 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001544
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001545 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001546 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1547 file, linenum, newpeer->addr.ss_family, args[2]);
1548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
1550 }
1551
Emeric Brun32da3c42010-09-23 18:39:19 +02001552 if (strcmp(newpeer->id, localpeer) == 0) {
1553 /* Current is local peer, it define a frontend */
1554 newpeer->local = 1;
1555
1556 if (!curpeers->peers_fe) {
1557 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1558 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1559 err_code |= ERR_ALERT | ERR_ABORT;
1560 goto out;
1561 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001562
Willy Tarreau237250c2011-07-29 01:49:03 +02001563 init_new_proxy(curpeers->peers_fe);
1564 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001565
1566 curpeers->peers_fe->last_change = now.tv_sec;
1567 curpeers->peers_fe->id = strdup(args[1]);
1568 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001569 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1571 curpeers->peers_fe->timeout.connect = 5000;
1572 curpeers->peers_fe->accept = peer_accept;
1573 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001574 curpeers->peers_fe->conf.file = strdup(file);
1575 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001576
1577 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1578
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001579 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1580 if (err_msg && *err_msg) {
1581 indent_msg(&err_msg, 2);
1582 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1583 }
1584 else
1585 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1586 file, linenum, args[0], args[1], args[2]);
1587 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 err_code |= ERR_FATAL;
1589 goto out;
1590 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001591
1592 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1593 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1594 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1595 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1596 l->accept = session_accept;
1597 l->handler = process_session;
1598 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1599 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1600 global.maxsock += l->maxconn;
1601 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001602 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001603 else {
1604 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1605 file, linenum, args[0], args[1],
1606 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1607 err_code |= ERR_FATAL;
1608 goto out;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
1611 } /* neither "peer" nor "peers" */
1612 else if (*args[0] != 0) {
1613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
1616 }
1617
1618out:
1619 return err_code;
1620}
1621
1622
Willy Tarreau3842f002009-06-14 11:39:52 +02001623int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624{
1625 static struct proxy *curproxy = NULL;
1626 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001627 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001628 int rc;
1629 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001630 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001631 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001632 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001633 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001634 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636 if (!strcmp(args[0], "listen"))
1637 rc = PR_CAP_LISTEN;
1638 else if (!strcmp(args[0], "frontend"))
1639 rc = PR_CAP_FE | PR_CAP_RS;
1640 else if (!strcmp(args[0], "backend"))
1641 rc = PR_CAP_BE | PR_CAP_RS;
1642 else if (!strcmp(args[0], "ruleset"))
1643 rc = PR_CAP_RS;
1644 else
1645 rc = PR_CAP_NONE;
1646
1647 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 if (!*args[1]) {
1649 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1650 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_ABORT;
1653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001655
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001656 err = invalid_char(args[1]);
1657 if (err) {
1658 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1659 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001661 }
1662
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001663 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1664 /*
1665 * If there are two proxies with the same name only following
1666 * combinations are allowed:
1667 *
1668 * listen backend frontend ruleset
1669 * listen - - - -
1670 * backend - - OK -
1671 * frontend - OK - -
1672 * ruleset - - - -
1673 */
1674
1675 if (!strcmp(curproxy->id, args[1]) &&
1676 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1677 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001678 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1679 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1680 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001682 }
1683 }
1684
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1686 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001687 err_code |= ERR_ALERT | ERR_ABORT;
1688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001689 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001690
Willy Tarreau97cb7802010-01-03 20:23:58 +01001691 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 curproxy->next = proxy;
1693 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001694 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001695 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001696 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001698 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699
1700 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001701 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001702 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001703 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001704
Willy Tarreau4348fad2012-09-20 16:48:07 +02001705 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1706
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001707 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1708 if (err_msg && *err_msg) {
1709 indent_msg(&err_msg, 2);
1710 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1711 }
1712 else
1713 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1714 file, linenum, args[0], args[1], args[2]);
1715 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_FATAL;
1717 goto out;
1718 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001719
Willy Tarreau4348fad2012-09-20 16:48:07 +02001720 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001721 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001722 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 }
1724
1725 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001726 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001727 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001728
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001731 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001732 curproxy->no_options = defproxy.no_options;
1733 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001734 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001735 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001736 curproxy->except_net = defproxy.except_net;
1737 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001738 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001739 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001741 if (defproxy.fwdfor_hdr_len) {
1742 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1743 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1744 }
1745
Willy Tarreaub86db342009-11-30 11:50:16 +01001746 if (defproxy.orgto_hdr_len) {
1747 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1748 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1749 }
1750
Mark Lamourinec2247f02012-01-04 13:02:01 -05001751 if (defproxy.server_id_hdr_len) {
1752 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1753 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1754 }
1755
Willy Tarreau977b8e42006-12-29 14:19:17 +01001756 if (curproxy->cap & PR_CAP_FE) {
1757 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001758 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001759 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001760
1761 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001762 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1763 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001764
1765 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767
Willy Tarreau977b8e42006-12-29 14:19:17 +01001768 if (curproxy->cap & PR_CAP_BE) {
1769 curproxy->fullconn = defproxy.fullconn;
1770 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001772 if (defproxy.check_req) {
1773 curproxy->check_req = calloc(1, defproxy.check_len);
1774 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1775 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001776 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001778 if (defproxy.expect_str) {
1779 curproxy->expect_str = strdup(defproxy.expect_str);
1780 if (defproxy.expect_regex) {
1781 /* note: this regex is known to be valid */
1782 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1783 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1784 }
1785 }
1786
Willy Tarreau67402132012-05-31 20:40:20 +02001787 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001788 if (defproxy.cookie_name)
1789 curproxy->cookie_name = strdup(defproxy.cookie_name);
1790 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001791 if (defproxy.cookie_domain)
1792 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001793
Willy Tarreau31936852010-10-06 16:59:56 +02001794 if (defproxy.cookie_maxidle)
1795 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1796
1797 if (defproxy.cookie_maxlife)
1798 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1799
Emeric Brun647caf12009-06-30 17:57:00 +02001800 if (defproxy.rdp_cookie_name)
1801 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1802 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1803
Willy Tarreau01732802007-11-01 22:48:15 +01001804 if (defproxy.url_param_name)
1805 curproxy->url_param_name = strdup(defproxy.url_param_name);
1806 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001807
Benoitaffb4812009-03-25 13:02:10 +01001808 if (defproxy.hh_name)
1809 curproxy->hh_name = strdup(defproxy.hh_name);
1810 curproxy->hh_len = defproxy.hh_len;
1811 curproxy->hh_match_domain = defproxy.hh_match_domain;
1812
Willy Tarreauef9a3602012-12-08 22:29:20 +01001813 if (defproxy.conn_src.iface_name)
1814 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1815 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1816 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001819 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001820 if (defproxy.capture_name)
1821 curproxy->capture_name = strdup(defproxy.capture_name);
1822 curproxy->capture_namelen = defproxy.capture_namelen;
1823 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825
Willy Tarreau977b8e42006-12-29 14:19:17 +01001826 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001827 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001828 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001829 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001830 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 curproxy->uri_auth = defproxy.uri_auth;
1832 curproxy->mon_net = defproxy.mon_net;
1833 curproxy->mon_mask = defproxy.mon_mask;
1834 if (defproxy.monitor_uri)
1835 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1836 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001837 if (defproxy.defbe.name)
1838 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001839
1840 /* get either a pointer to the logformat string or a copy of it */
1841 curproxy->logformat_string = defproxy.logformat_string;
1842 if (curproxy->logformat_string &&
1843 curproxy->logformat_string != default_http_log_format &&
1844 curproxy->logformat_string != default_tcp_log_format &&
1845 curproxy->logformat_string != clf_http_log_format)
1846 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001847 }
1848
1849 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001850 curproxy->timeout.connect = defproxy.timeout.connect;
1851 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001852 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001853 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001854 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001855 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001856 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001857 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001858 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001859 }
1860
Willy Tarreaubaaee002006-06-26 02:48:02 +02001861 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001862
1863 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001864 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001865 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001866 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001867 LIST_INIT(&node->list);
1868 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1869 }
1870
Willy Tarreau196729e2012-05-31 19:30:26 +02001871 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1872 if (curproxy->uniqueid_format_string)
1873 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001874
1875 /* copy default header unique id */
1876 if (defproxy.header_unique_id)
1877 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1878
William Lallemand82fe75c2012-10-23 10:25:10 +02001879 /* default compression options */
1880 if (defproxy.comp != NULL) {
1881 curproxy->comp = calloc(1, sizeof(struct comp));
1882 curproxy->comp->algos = defproxy.comp->algos;
1883 curproxy->comp->types = defproxy.comp->types;
1884 }
1885
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001887 curproxy->conf.used_listener_id = EB_ROOT;
1888 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001889
Willy Tarreau93893792009-07-23 13:19:11 +02001890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 }
1892 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1893 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001894 /* FIXME-20070101: we should do this too at the end of the
1895 * config parsing to free all default values.
1896 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001897 free(defproxy.check_req);
1898 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001899 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001900 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001901 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001902 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001903 free(defproxy.capture_name);
1904 free(defproxy.monitor_uri);
1905 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001906 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001907 free(defproxy.fwdfor_hdr_name);
1908 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001909 free(defproxy.orgto_hdr_name);
1910 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001911 free(defproxy.server_id_hdr_name);
1912 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001913 free(defproxy.expect_str);
1914 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001915
Willy Tarreau39b06652012-06-01 10:58:06 +02001916 if (defproxy.logformat_string != default_http_log_format &&
1917 defproxy.logformat_string != default_tcp_log_format &&
1918 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001919 free(defproxy.logformat_string);
1920
1921 free(defproxy.uniqueid_format_string);
1922
Willy Tarreaua534fea2008-08-03 12:19:50 +02001923 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001924 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 /* we cannot free uri_auth because it might already be used */
1927 init_default_instance();
1928 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 else if (curproxy == NULL) {
1933 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
1937
Willy Tarreau977b8e42006-12-29 14:19:17 +01001938
1939 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001941 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001942 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001943 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001944
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 if (curproxy == &defproxy) {
1946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001950 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952
Emeric Bruned760922010-10-22 17:59:25 +02001953 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001954 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001959
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001960 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001961
1962 /* use default settings for unix sockets */
1963 bind_conf->ux.uid = global.unix_bind.ux.uid;
1964 bind_conf->ux.gid = global.unix_bind.ux.gid;
1965 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001966
1967 /* NOTE: the following line might create several listeners if there
1968 * are comma-separated IPs or port ranges. So all further processing
1969 * will have to be applied to all listeners created after last_listen.
1970 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001971 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1972 if (err_msg && *err_msg) {
1973 indent_msg(&err_msg, 2);
1974 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1975 }
1976 else
1977 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1978 file, linenum, args[0], args[1]);
1979 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001983
Willy Tarreau4348fad2012-09-20 16:48:07 +02001984 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1985 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001986 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001987 }
1988
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001989 cur_arg = 2;
1990 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001991 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001992 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001993 char *err;
1994
Willy Tarreau26982662012-09-12 23:17:10 +02001995 kw = bind_find_kw(args[cur_arg]);
1996 if (kw) {
1997 char *err = NULL;
1998 int code;
1999
2000 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002001 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2002 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002003 cur_arg += 1 + kw->skip ;
2004 err_code |= ERR_ALERT | ERR_FATAL;
2005 goto out;
2006 }
2007
Willy Tarreau4348fad2012-09-20 16:48:07 +02002008 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002009 err_code |= code;
2010
2011 if (code) {
2012 if (err && *err) {
2013 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002014 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002015 }
2016 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002017 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2018 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002019 if (code & ERR_FATAL) {
2020 free(err);
2021 cur_arg += 1 + kw->skip;
2022 goto out;
2023 }
2024 }
2025 free(err);
2026 cur_arg += 1 + kw->skip;
2027 continue;
2028 }
2029
Willy Tarreau8638f482012-09-18 18:01:17 +02002030 err = NULL;
2031 if (!bind_dumped) {
2032 bind_dump_kws(&err);
2033 indent_msg(&err, 4);
2034 bind_dumped = 1;
2035 }
2036
2037 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2038 file, linenum, args[0], args[1], args[cur_arg],
2039 err ? " Registered keywords :" : "", err ? err : "");
2040 free(err);
2041
Willy Tarreau93893792009-07-23 13:19:11 +02002042 err_code |= ERR_ALERT | ERR_FATAL;
2043 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002044 }
Willy Tarreau93893792009-07-23 13:19:11 +02002045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 }
2047 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2048 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2049 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 /* flush useless bits */
2058 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002061 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064
Willy Tarreau1c47f852006-07-09 08:22:27 +02002065 if (!*args[1]) {
2066 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002070 }
2071
Willy Tarreaua534fea2008-08-03 12:19:50 +02002072 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002073 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002074 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002075 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002076 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2077
Willy Tarreau93893792009-07-23 13:19:11 +02002078 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2081 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2082 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2083 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2084 else {
2085 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
2089 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002090 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002091 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002092
2093 if (curproxy == &defproxy) {
2094 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002098 }
2099
2100 if (!*args[1]) {
2101 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002105 }
2106
2107 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002108 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002110 if (curproxy->uuid <= 0) {
2111 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002112 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002115 }
2116
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002117 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2118 if (node) {
2119 struct proxy *target = container_of(node, struct proxy, conf.id);
2120 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2121 file, linenum, proxy_type_str(curproxy), curproxy->id,
2122 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
2125 }
2126 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002127 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002128 else if (!strcmp(args[0], "description")) {
2129 int i, len=0;
2130 char *d;
2131
Cyril Bonté99ed3272010-01-24 23:29:44 +01002132 if (curproxy == &defproxy) {
2133 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2134 file, linenum, args[0]);
2135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
2137 }
2138
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002139 if (!*args[1]) {
2140 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2141 file, linenum, args[0]);
2142 return -1;
2143 }
2144
2145 for(i=1; *args[i]; i++)
2146 len += strlen(args[i])+1;
2147
2148 d = (char *)calloc(1, len);
2149 curproxy->desc = d;
2150
2151 d += sprintf(d, "%s", args[1]);
2152 for(i=2; *args[i]; i++)
2153 d += sprintf(d, " %s", args[i]);
2154
2155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2157 curproxy->state = PR_STSTOPPED;
2158 }
2159 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2160 curproxy->state = PR_STNEW;
2161 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002162 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2163 int cur_arg = 1;
2164 unsigned int set = 0;
2165
2166 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002167 unsigned int low, high;
2168
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002169 if (strcmp(args[cur_arg], "all") == 0) {
2170 set = 0;
2171 break;
2172 }
2173 else if (strcmp(args[cur_arg], "odd") == 0) {
2174 set |= 0x55555555;
2175 }
2176 else if (strcmp(args[cur_arg], "even") == 0) {
2177 set |= 0xAAAAAAAA;
2178 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002179 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002180 char *dash = strchr(args[cur_arg], '-');
2181
2182 low = high = str2uic(args[cur_arg]);
2183 if (dash)
2184 high = str2uic(dash + 1);
2185
2186 if (high < low) {
2187 unsigned int swap = low;
2188 low = high;
2189 high = swap;
2190 }
2191
2192 if (low < 1 || high > 32) {
2193 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002197 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002198
2199 if (high > global.nbproc) {
2200 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2201 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002203 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002204 while (low <= high)
2205 set |= 1 << (low++ - 1);
2206 }
2207 else {
2208 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2209 file, linenum, args[0]);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002212 }
2213 cur_arg++;
2214 }
2215 curproxy->bind_proc = set;
2216 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002217 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002218 if (curproxy == &defproxy) {
2219 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002222 }
2223
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002224 err = invalid_char(args[1]);
2225 if (err) {
2226 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2227 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002229 }
2230
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002231 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2232 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2233 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002236 }
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2239 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 if (*(args[1]) == 0) {
2245 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_FATAL;
2248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002250
Willy Tarreau67402132012-05-31 20:40:20 +02002251 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002252 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002253 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002254 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 curproxy->cookie_name = strdup(args[1]);
2256 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002257
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 cur_arg = 2;
2259 while (*(args[cur_arg])) {
2260 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002261 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
2263 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002264 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 }
2266 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002267 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }
2269 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002270 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 }
2272 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002273 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002275 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002276 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002279 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002281 else if (!strcmp(args[cur_arg], "httponly")) {
2282 curproxy->ck_opts |= PR_CK_HTTPONLY;
2283 }
2284 else if (!strcmp(args[cur_arg], "secure")) {
2285 curproxy->ck_opts |= PR_CK_SECURE;
2286 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002287 else if (!strcmp(args[cur_arg], "domain")) {
2288 if (!*args[cur_arg + 1]) {
2289 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2290 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002293 }
2294
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002295 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002296 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002297 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2298 " dots nor does not start with a dot."
2299 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002300 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002301 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002302 }
2303
2304 err = invalid_domainchar(args[cur_arg + 1]);
2305 if (err) {
2306 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2307 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002310 }
2311
Willy Tarreau68a897b2009-12-03 23:28:34 +01002312 if (!curproxy->cookie_domain) {
2313 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2314 } else {
2315 /* one domain was already specified, add another one by
2316 * building the string which will be returned along with
2317 * the cookie.
2318 */
2319 char *new_ptr;
2320 int new_len = strlen(curproxy->cookie_domain) +
2321 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2322 new_ptr = malloc(new_len);
2323 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2324 free(curproxy->cookie_domain);
2325 curproxy->cookie_domain = new_ptr;
2326 }
Willy Tarreau31936852010-10-06 16:59:56 +02002327 cur_arg++;
2328 }
2329 else if (!strcmp(args[cur_arg], "maxidle")) {
2330 unsigned int maxidle;
2331 const char *res;
2332
2333 if (!*args[cur_arg + 1]) {
2334 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2335 file, linenum, args[cur_arg]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339
2340 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2341 if (res) {
2342 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2343 file, linenum, *res, args[cur_arg]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347 curproxy->cookie_maxidle = maxidle;
2348 cur_arg++;
2349 }
2350 else if (!strcmp(args[cur_arg], "maxlife")) {
2351 unsigned int maxlife;
2352 const char *res;
2353
2354 if (!*args[cur_arg + 1]) {
2355 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2356 file, linenum, args[cur_arg]);
2357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
2359 }
2360
2361 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2362 if (res) {
2363 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2364 file, linenum, *res, args[cur_arg]);
2365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
2367 }
2368 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002369 cur_arg++;
2370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002372 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 +02002373 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
2377 cur_arg++;
2378 }
Willy Tarreau67402132012-05-31 20:40:20 +02002379 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2381 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 }
2384
Willy Tarreau67402132012-05-31 20:40:20 +02002385 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002390
Willy Tarreau67402132012-05-31 20:40:20 +02002391 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002392 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2393 file, linenum);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002397 else if (!strcmp(args[0], "persist")) { /* persist */
2398 if (*(args[1]) == 0) {
2399 Alert("parsing [%s:%d] : missing persist method.\n",
2400 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002403 }
2404
2405 if (!strncmp(args[1], "rdp-cookie", 10)) {
2406 curproxy->options2 |= PR_O2_RDPC_PRST;
2407
Emeric Brunb982a3d2010-01-04 15:45:53 +01002408 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002409 const char *beg, *end;
2410
2411 beg = args[1] + 11;
2412 end = strchr(beg, ')');
2413
2414 if (!end || end == beg) {
2415 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2416 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002419 }
2420
2421 free(curproxy->rdp_cookie_name);
2422 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2423 curproxy->rdp_cookie_len = end-beg;
2424 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002425 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002426 free(curproxy->rdp_cookie_name);
2427 curproxy->rdp_cookie_name = strdup("msts");
2428 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2429 }
2430 else { /* syntax */
2431 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002435 }
2436 }
2437 else {
2438 Alert("parsing [%s:%d] : unknown persist method.\n",
2439 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002442 }
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002445 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002447 if (curproxy == &defproxy) {
2448 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
2451 }
2452
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002455
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002457 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002463 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 curproxy->appsession_name = strdup(args[1]);
2465 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2466 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002467 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2468 if (err) {
2469 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2470 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002473 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002474 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002475
Willy Tarreau51041c72007-09-09 21:56:53 +02002476 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_ABORT;
2479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002481
2482 cur_arg = 6;
2483 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002484 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2485 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002486 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002487 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002488 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002489 } else if (!strcmp(args[cur_arg], "prefix")) {
2490 curproxy->options2 |= PR_O2_AS_PFX;
2491 } else if (!strcmp(args[cur_arg], "mode")) {
2492 if (!*args[cur_arg + 1]) {
2493 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2494 file, linenum, args[0], args[cur_arg]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
2499 cur_arg++;
2500 if (!strcmp(args[cur_arg], "query-string")) {
2501 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2502 curproxy->options2 |= PR_O2_AS_M_QS;
2503 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2504 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2505 curproxy->options2 |= PR_O2_AS_M_PP;
2506 } else {
2507 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002512 cur_arg++;
2513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 } /* Url App Session */
2515 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002516 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002518
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002520 if (curproxy == &defproxy) {
2521 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
2524 }
2525
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (*(args[4]) == 0) {
2527 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2528 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002532 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 curproxy->capture_name = strdup(args[2]);
2534 curproxy->capture_namelen = strlen(curproxy->capture_name);
2535 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 curproxy->to_log |= LW_COOKIE;
2537 }
2538 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2539 struct cap_hdr *hdr;
2540
2541 if (curproxy == &defproxy) {
2542 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 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 }
2546
2547 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2548 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2549 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553
2554 hdr = calloc(sizeof(struct cap_hdr), 1);
2555 hdr->next = curproxy->req_cap;
2556 hdr->name = strdup(args[3]);
2557 hdr->namelen = strlen(args[3]);
2558 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002559 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 hdr->index = curproxy->nb_req_cap++;
2561 curproxy->req_cap = hdr;
2562 curproxy->to_log |= LW_REQHDR;
2563 }
2564 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2565 struct cap_hdr *hdr;
2566
2567 if (curproxy == &defproxy) {
2568 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 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572
2573 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2574 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2575 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
2579 hdr = calloc(sizeof(struct cap_hdr), 1);
2580 hdr->next = curproxy->rsp_cap;
2581 hdr->name = strdup(args[3]);
2582 hdr->namelen = strlen(args[3]);
2583 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002584 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 hdr->index = curproxy->nb_rsp_cap++;
2586 curproxy->rsp_cap = hdr;
2587 curproxy->to_log |= LW_RSPHDR;
2588 }
2589 else {
2590 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 }
2595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002599
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 if (*(args[1]) == 0) {
2601 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
2606 curproxy->conn_retries = atol(args[1]);
2607 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002608 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002609 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002610
2611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
Willy Tarreau20b0de52012-12-24 15:45:22 +01002617 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2618 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2619 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2620 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2621 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2622 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 +01002623 file, linenum, args[0]);
2624 err_code |= ERR_WARN;
2625 }
2626
Willy Tarreauff011f22011-01-06 17:51:27 +01002627 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002628
Willy Tarreauff011f22011-01-06 17:51:27 +01002629 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002630 err_code |= ERR_ALERT | ERR_ABORT;
2631 goto out;
2632 }
2633
Willy Tarreauff011f22011-01-06 17:51:27 +01002634 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2635 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002636 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002637 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2638 /* set the header name and length into the proxy structure */
2639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2640 err_code |= ERR_WARN;
2641
2642 if (!*args[1]) {
2643 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2644 file, linenum, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 /* set the desired header name */
2650 free(curproxy->server_id_hdr_name);
2651 curproxy->server_id_hdr_name = strdup(args[1]);
2652 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2653 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002654 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002655 if (curproxy == &defproxy) {
2656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002659 }
2660
Willy Tarreauef6494c2010-01-28 17:12:36 +01002661 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002662 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002666 }
2667
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002668 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2669 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2670 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002673 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002674
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002675 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002676 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002677 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680
Cyril Bonté99ed3272010-01-24 23:29:44 +01002681 if (curproxy == &defproxy) {
2682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
Willy Tarreau4baae242012-12-27 12:00:31 +01002687 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2688 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2689 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002692 }
2693
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002694 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002695 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2696 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002697 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002698 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 struct switching_rule *rule;
2700
Willy Tarreaub099aca2008-10-12 17:26:37 +02002701 if (curproxy == &defproxy) {
2702 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002705 }
2706
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709
2710 if (*(args[1]) == 0) {
2711 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 }
2715
Willy Tarreauef6494c2010-01-28 17:12:36 +01002716 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002721 }
2722
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002723 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2724 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2725 file, linenum, errmsg);
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 Tarreauf1e98b82010-01-28 17:59:39 +01002730 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002731
Willy Tarreau55ea7572007-06-17 19:56:27 +02002732 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2733 rule->cond = cond;
2734 rule->be.name = strdup(args[1]);
2735 LIST_INIT(&rule->list);
2736 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2737 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002738 else if (strcmp(args[0], "use-server") == 0) {
2739 struct server_rule *rule;
2740
2741 if (curproxy == &defproxy) {
2742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746
2747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2748 err_code |= ERR_WARN;
2749
2750 if (*(args[1]) == 0) {
2751 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2757 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2758 file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002763 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2764 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2765 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
2770 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2771
2772 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2773 rule->cond = cond;
2774 rule->srv.name = strdup(args[1]);
2775 LIST_INIT(&rule->list);
2776 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2777 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2778 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002779 else if ((!strcmp(args[0], "force-persist")) ||
2780 (!strcmp(args[0], "ignore-persist"))) {
2781 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002782
2783 if (curproxy == &defproxy) {
2784 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787 }
2788
2789 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2790 err_code |= ERR_WARN;
2791
Willy Tarreauef6494c2010-01-28 17:12:36 +01002792 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002793 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2794 file, linenum, args[0]);
2795 err_code |= ERR_ALERT | ERR_FATAL;
2796 goto out;
2797 }
2798
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002799 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2800 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2801 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804 }
2805
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002806 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002807
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002808 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002809 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002810 if (!strcmp(args[0], "force-persist")) {
2811 rule->type = PERSIST_TYPE_FORCE;
2812 } else {
2813 rule->type = PERSIST_TYPE_IGNORE;
2814 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002815 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002816 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002817 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002818 else if (!strcmp(args[0], "stick-table")) {
2819 int myidx = 1;
2820
Emeric Brun32da3c42010-09-23 18:39:19 +02002821 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002822 curproxy->table.type = (unsigned int)-1;
2823 while (*args[myidx]) {
2824 const char *err;
2825
2826 if (strcmp(args[myidx], "size") == 0) {
2827 myidx++;
2828 if (!*(args[myidx])) {
2829 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2830 file, linenum, args[myidx-1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2835 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2836 file, linenum, *err, args[myidx-1]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002840 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002841 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002842 else if (strcmp(args[myidx], "peers") == 0) {
2843 myidx++;
2844 if (!*(args[myidx])) {
2845 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2846 file, linenum, args[myidx-1]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850 curproxy->table.peers.name = strdup(args[myidx++]);
2851 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002852 else if (strcmp(args[myidx], "expire") == 0) {
2853 myidx++;
2854 if (!*(args[myidx])) {
2855 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2856 file, linenum, args[myidx-1]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2861 if (err) {
2862 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2863 file, linenum, *err, args[myidx-1]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002868 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002869 }
2870 else if (strcmp(args[myidx], "nopurge") == 0) {
2871 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002872 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002873 }
2874 else if (strcmp(args[myidx], "type") == 0) {
2875 myidx++;
2876 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2877 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2878 file, linenum, args[myidx]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002882 /* myidx already points to next arg */
2883 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002884 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002885 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002886 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002887
2888 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002889 nw = args[myidx];
2890 while (*nw) {
2891 /* the "store" keyword supports a comma-separated list */
2892 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002893 sa = NULL; /* store arg */
2894 while (*nw && *nw != ',') {
2895 if (*nw == '(') {
2896 *nw = 0;
2897 sa = ++nw;
2898 while (*nw != ')') {
2899 if (!*nw) {
2900 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2901 file, linenum, args[0], cw);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905 nw++;
2906 }
2907 *nw = '\0';
2908 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002909 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002910 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002911 if (*nw)
2912 *nw++ = '\0';
2913 type = stktable_get_data_type(cw);
2914 if (type < 0) {
2915 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2916 file, linenum, args[0], cw);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
Willy Tarreauac782882010-06-20 10:41:54 +02002920
2921 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2922 switch (err) {
2923 case PE_NONE: break;
2924 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002925 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002928 break;
2929
2930 case PE_ARG_MISSING:
2931 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2932 file, linenum, args[0], cw);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935
2936 case PE_ARG_NOT_USED:
2937 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2938 file, linenum, args[0], cw);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941
2942 default:
2943 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2944 file, linenum, args[0], cw);
2945 err_code |= ERR_ALERT | ERR_FATAL;
2946 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002947 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002948 }
2949 myidx++;
2950 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002951 else {
2952 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2953 file, linenum, args[myidx]);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 }
2958
2959 if (!curproxy->table.size) {
2960 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2961 file, linenum);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (curproxy->table.type == (unsigned int)-1) {
2967 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2968 file, linenum);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972 }
2973 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002974 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002975 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 int myidx = 0;
2977 const char *name = NULL;
2978 int flags;
2979
2980 if (curproxy == &defproxy) {
2981 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
2985
2986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2987 err_code |= ERR_WARN;
2988 goto out;
2989 }
2990
2991 myidx++;
2992 if ((strcmp(args[myidx], "store") == 0) ||
2993 (strcmp(args[myidx], "store-request") == 0)) {
2994 myidx++;
2995 flags = STK_IS_STORE;
2996 }
2997 else if (strcmp(args[myidx], "store-response") == 0) {
2998 myidx++;
2999 flags = STK_IS_STORE | STK_ON_RSP;
3000 }
3001 else if (strcmp(args[myidx], "match") == 0) {
3002 myidx++;
3003 flags = STK_IS_MATCH;
3004 }
3005 else if (strcmp(args[myidx], "on") == 0) {
3006 myidx++;
3007 flags = STK_IS_MATCH | STK_IS_STORE;
3008 }
3009 else {
3010 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (*(args[myidx]) == 0) {
3016 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003021 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003023 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
3027
3028 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003029 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3031 file, linenum, args[0], expr->fetch->kw);
3032 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003033 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 goto out;
3035 }
3036 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003037 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3039 file, linenum, args[0], expr->fetch->kw);
3040 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003041 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003042 goto out;
3043 }
3044 }
3045
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003046 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3047 if (expr->fetch->cap & SMP_CAP_L7)
3048 curproxy->acl_requires |= ACL_USE_L7_ANY;
3049
Emeric Brunb982a3d2010-01-04 15:45:53 +01003050 if (strcmp(args[myidx], "table") == 0) {
3051 myidx++;
3052 name = args[myidx++];
3053 }
3054
Willy Tarreauef6494c2010-01-28 17:12:36 +01003055 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003056 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3057 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3058 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003060 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003061 goto out;
3062 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003063 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003064 else if (*(args[myidx])) {
3065 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3066 file, linenum, args[0], args[myidx]);
3067 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003068 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003069 goto out;
3070 }
Emeric Brun97679e72010-09-23 17:56:44 +02003071 if (flags & STK_ON_RSP)
3072 err_code |= warnif_cond_requires_req(cond, file, linenum);
3073 else
3074 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003075
Emeric Brunb982a3d2010-01-04 15:45:53 +01003076 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3077 rule->cond = cond;
3078 rule->expr = expr;
3079 rule->flags = flags;
3080 rule->table.name = name ? strdup(name) : NULL;
3081 LIST_INIT(&rule->list);
3082 if (flags & STK_ON_RSP)
3083 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3084 else
3085 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003090
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3092 curproxy->uri_auth = NULL; /* we must detach from the default config */
3093
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003094 if (!*args[1]) {
3095 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003096 } else if (!strcmp(args[1], "admin")) {
3097 struct stats_admin_rule *rule;
3098
3099 if (curproxy == &defproxy) {
3100 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
3105 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3106 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3107 err_code |= ERR_ALERT | ERR_ABORT;
3108 goto out;
3109 }
3110
3111 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3112 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3113 file, linenum, args[0], args[1]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003117 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3118 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3119 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123
3124 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3125
3126 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3127 rule->cond = cond;
3128 LIST_INIT(&rule->list);
3129 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 } else if (!strcmp(args[1], "uri")) {
3131 if (*(args[2]) == 0) {
3132 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_ABORT;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
3140 } else if (!strcmp(args[1], "realm")) {
3141 if (*(args[2]) == 0) {
3142 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3146 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_ABORT;
3148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003150 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003151 unsigned interval;
3152
3153 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3154 if (err) {
3155 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3156 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003159 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02003163 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003164 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003165 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003166
3167 if (curproxy == &defproxy) {
3168 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
3171 }
3172
3173 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3174 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3175 err_code |= ERR_ALERT | ERR_ABORT;
3176 goto out;
3177 }
3178
Willy Tarreauff011f22011-01-06 17:51:27 +01003179 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3180 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003181 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3182 file, linenum, args[0]);
3183 err_code |= ERR_WARN;
3184 }
3185
Willy Tarreauff011f22011-01-06 17:51:27 +01003186 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003187
Willy Tarreauff011f22011-01-06 17:51:27 +01003188 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003189 err_code |= ERR_ALERT | ERR_ABORT;
3190 goto out;
3191 }
3192
Willy Tarreauff011f22011-01-06 17:51:27 +01003193 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3194 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003195
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 } else if (!strcmp(args[1], "auth")) {
3197 if (*(args[2]) == 0) {
3198 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3202 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_ALERT | ERR_ABORT;
3204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 }
3206 } else if (!strcmp(args[1], "scope")) {
3207 if (*(args[2]) == 0) {
3208 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_FATAL;
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_ABORT;
3214 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
3216 } else if (!strcmp(args[1], "enable")) {
3217 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3218 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_ABORT;
3220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003222 } else if (!strcmp(args[1], "hide-version")) {
3223 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_ABORT;
3226 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003227 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003228 } else if (!strcmp(args[1], "show-legends")) {
3229 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3230 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3231 err_code |= ERR_ALERT | ERR_ABORT;
3232 goto out;
3233 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003234 } else if (!strcmp(args[1], "show-node")) {
3235
3236 if (*args[2]) {
3237 int i;
3238 char c;
3239
3240 for (i=0; args[2][i]; i++) {
3241 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003242 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3243 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003244 break;
3245 }
3246
3247 if (!i || args[2][i]) {
3248 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3249 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3250 file, linenum, args[0], args[1]);
3251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
3254 }
3255
3256 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3257 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3258 err_code |= ERR_ALERT | ERR_ABORT;
3259 goto out;
3260 }
3261 } else if (!strcmp(args[1], "show-desc")) {
3262 char *desc = NULL;
3263
3264 if (*args[2]) {
3265 int i, len=0;
3266 char *d;
3267
3268 for(i=2; *args[i]; i++)
3269 len += strlen(args[i])+1;
3270
3271 desc = d = (char *)calloc(1, len);
3272
3273 d += sprintf(d, "%s", args[2]);
3274 for(i=3; *args[i]; i++)
3275 d += sprintf(d, " %s", args[i]);
3276 }
3277
3278 if (!*args[2] && !global.desc)
3279 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3280 file, linenum, args[1]);
3281 else {
3282 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3283 free(desc);
3284 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3285 err_code |= ERR_ALERT | ERR_ABORT;
3286 goto out;
3287 }
3288 free(desc);
3289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003291stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003292 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 +01003293 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 }
3297 }
3298 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003299 int optnum;
3300
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003301 if (*(args[1]) == '\0') {
3302 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3303 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
3305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307
3308 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3309 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003310 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3311 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3312 file, linenum, cfg_opts[optnum].name);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
Willy Tarreau93893792009-07-23 13:19:11 +02003316 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3317 err_code |= ERR_WARN;
3318 goto out;
3319 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003320
Willy Tarreau3842f002009-06-14 11:39:52 +02003321 curproxy->no_options &= ~cfg_opts[optnum].val;
3322 curproxy->options &= ~cfg_opts[optnum].val;
3323
3324 switch (kwm) {
3325 case KWM_STD:
3326 curproxy->options |= cfg_opts[optnum].val;
3327 break;
3328 case KWM_NO:
3329 curproxy->no_options |= cfg_opts[optnum].val;
3330 break;
3331 case KWM_DEF: /* already cleared */
3332 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003333 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003334
Willy Tarreau93893792009-07-23 13:19:11 +02003335 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003336 }
3337 }
3338
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003339 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3340 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003341 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3342 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3343 file, linenum, cfg_opts2[optnum].name);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346 }
Willy Tarreau93893792009-07-23 13:19:11 +02003347 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3348 err_code |= ERR_WARN;
3349 goto out;
3350 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003351
Willy Tarreau3842f002009-06-14 11:39:52 +02003352 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3353 curproxy->options2 &= ~cfg_opts2[optnum].val;
3354
3355 switch (kwm) {
3356 case KWM_STD:
3357 curproxy->options2 |= cfg_opts2[optnum].val;
3358 break;
3359 case KWM_NO:
3360 curproxy->no_options2 |= cfg_opts2[optnum].val;
3361 break;
3362 case KWM_DEF: /* already cleared */
3363 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003364 }
Willy Tarreau93893792009-07-23 13:19:11 +02003365 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003366 }
3367 }
3368
Willy Tarreau3842f002009-06-14 11:39:52 +02003369 if (kwm != KWM_STD) {
3370 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003371 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003374 }
3375
Emeric Brun3a058f32009-06-30 18:26:00 +02003376 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003377 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003379 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003380 if (*(args[2]) != '\0') {
3381 if (!strcmp(args[2], "clf")) {
3382 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003383 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003384 } else {
3385 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003388 }
3389 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003390 if (curproxy->logformat_string != default_http_log_format &&
3391 curproxy->logformat_string != default_tcp_log_format &&
3392 curproxy->logformat_string != clf_http_log_format)
3393 free(curproxy->logformat_string);
3394 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003395 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003396 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003398 if (curproxy->logformat_string != default_http_log_format &&
3399 curproxy->logformat_string != default_tcp_log_format &&
3400 curproxy->logformat_string != clf_http_log_format)
3401 free(curproxy->logformat_string);
3402 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 else if (!strcmp(args[1], "tcpka")) {
3405 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003406 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003407 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003408
3409 if (curproxy->cap & PR_CAP_FE)
3410 curproxy->options |= PR_O_TCP_CLI_KA;
3411 if (curproxy->cap & PR_CAP_BE)
3412 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 }
3414 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_WARN;
3417
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003419 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003420 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003421 curproxy->options2 &= ~PR_O2_CHK_ANY;
3422 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 if (!*args[2]) { /* no argument */
3424 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3425 curproxy->check_len = strlen(DEF_CHECK_REQ);
3426 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003427 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 curproxy->check_req = (char *)malloc(reqlen);
3429 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003430 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003432 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 if (*args[4])
3434 reqlen += strlen(args[4]);
3435 else
3436 reqlen += strlen("HTTP/1.0");
3437
3438 curproxy->check_req = (char *)malloc(reqlen);
3439 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003440 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003442 }
3443 else if (!strcmp(args[1], "ssl-hello-chk")) {
3444 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003446 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003447
Willy Tarreaua534fea2008-08-03 12:19:50 +02003448 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003449 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003450 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003451 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 }
Willy Tarreau23677902007-05-08 23:50:35 +02003453 else if (!strcmp(args[1], "smtpchk")) {
3454 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003455 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003456 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003457 curproxy->options2 &= ~PR_O2_CHK_ANY;
3458 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003459
3460 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3461 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3462 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3463 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3464 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3465 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3466 curproxy->check_req = (char *)malloc(reqlen);
3467 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3468 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3469 } else {
3470 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3471 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3472 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3473 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3474 }
3475 }
3476 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003477 else if (!strcmp(args[1], "lb-agent-chk")) {
3478 /* use dynmaic health check */
3479 free(curproxy->check_req);
3480 curproxy->check_req = NULL;
3481 curproxy->options2 &= ~PR_O2_CHK_ANY;
3482 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3483 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003484 else if (!strcmp(args[1], "pgsql-check")) {
3485 /* use PostgreSQL request to check servers' health */
3486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3487 err_code |= ERR_WARN;
3488
3489 free(curproxy->check_req);
3490 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003491 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003492 curproxy->options2 |= PR_O2_PGSQL_CHK;
3493
3494 if (*(args[2])) {
3495 int cur_arg = 2;
3496
3497 while (*(args[cur_arg])) {
3498 if (strcmp(args[cur_arg], "user") == 0) {
3499 char * packet;
3500 uint32_t packet_len;
3501 uint32_t pv;
3502
3503 /* suboption header - needs additional argument for it */
3504 if (*(args[cur_arg+1]) == 0) {
3505 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3506 file, linenum, args[0], args[1], args[cur_arg]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510
3511 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3512 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3513 pv = htonl(0x30000); /* protocol version 3.0 */
3514
3515 packet = (char*) calloc(1, packet_len);
3516
3517 memcpy(packet + 4, &pv, 4);
3518
3519 /* copy "user" */
3520 memcpy(packet + 8, "user", 4);
3521
3522 /* copy username */
3523 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3524
3525 free(curproxy->check_req);
3526 curproxy->check_req = packet;
3527 curproxy->check_len = packet_len;
3528
3529 packet_len = htonl(packet_len);
3530 memcpy(packet, &packet_len, 4);
3531 cur_arg += 2;
3532 } else {
3533 /* unknown suboption - catchall */
3534 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3535 file, linenum, args[0], args[1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 } /* end while loop */
3540 }
3541 }
3542
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003543 else if (!strcmp(args[1], "redis-check")) {
3544 /* use REDIS PING request to check servers' health */
3545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3546 err_code |= ERR_WARN;
3547
3548 free(curproxy->check_req);
3549 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003550 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003551 curproxy->options2 |= PR_O2_REDIS_CHK;
3552
3553 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3554 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3555 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3556 }
3557
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003558 else if (!strcmp(args[1], "mysql-check")) {
3559 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003560 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3561 err_code |= ERR_WARN;
3562
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003563 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003564 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003565 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003566 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003567
3568 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3569 * const char mysql40_client_auth_pkt[] = {
3570 * "\x0e\x00\x00" // packet length
3571 * "\x01" // packet number
3572 * "\x00\x00" // client capabilities
3573 * "\x00\x00\x01" // max packet
3574 * "haproxy\x00" // username (null terminated string)
3575 * "\x00" // filler (always 0x00)
3576 * "\x01\x00\x00" // packet length
3577 * "\x00" // packet number
3578 * "\x01" // COM_QUIT command
3579 * };
3580 */
3581
3582 if (*(args[2])) {
3583 int cur_arg = 2;
3584
3585 while (*(args[cur_arg])) {
3586 if (strcmp(args[cur_arg], "user") == 0) {
3587 char *mysqluser;
3588 int packetlen, reqlen, userlen;
3589
3590 /* suboption header - needs additional argument for it */
3591 if (*(args[cur_arg+1]) == 0) {
3592 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3593 file, linenum, args[0], args[1], args[cur_arg]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597 mysqluser = args[cur_arg + 1];
3598 userlen = strlen(mysqluser);
3599 packetlen = userlen + 7;
3600 reqlen = packetlen + 9;
3601
3602 free(curproxy->check_req);
3603 curproxy->check_req = (char *)calloc(1, reqlen);
3604 curproxy->check_len = reqlen;
3605
3606 snprintf(curproxy->check_req, 4, "%c%c%c",
3607 ((unsigned char) packetlen & 0xff),
3608 ((unsigned char) (packetlen >> 8) & 0xff),
3609 ((unsigned char) (packetlen >> 16) & 0xff));
3610
3611 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003612 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003613 curproxy->check_req[8] = 1;
3614 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3615 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3616 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3617 cur_arg += 2;
3618 } else {
3619 /* unknown suboption - catchall */
3620 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3621 file, linenum, args[0], args[1]);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 } /* end while loop */
3626 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003627 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003628 else if (!strcmp(args[1], "ldap-check")) {
3629 /* use LDAP request to check servers' health */
3630 free(curproxy->check_req);
3631 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003632 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003633 curproxy->options2 |= PR_O2_LDAP_CHK;
3634
3635 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3636 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3637 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3638 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003639 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003640 int cur_arg;
3641
3642 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3643 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003644 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003645
Willy Tarreau87cf5142011-08-19 22:57:24 +02003646 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003647
3648 free(curproxy->fwdfor_hdr_name);
3649 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3650 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3651
3652 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3653 cur_arg = 2;
3654 while (*(args[cur_arg])) {
3655 if (!strcmp(args[cur_arg], "except")) {
3656 /* suboption except - needs additional argument for it */
3657 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3658 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3659 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 }
3663 /* flush useless bits */
3664 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 cur_arg += 2;
3666 } else if (!strcmp(args[cur_arg], "header")) {
3667 /* suboption header - needs additional argument for it */
3668 if (*(args[cur_arg+1]) == 0) {
3669 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3670 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003673 }
3674 free(curproxy->fwdfor_hdr_name);
3675 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3676 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3677 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003678 } else if (!strcmp(args[cur_arg], "if-none")) {
3679 curproxy->options &= ~PR_O_FF_ALWAYS;
3680 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003681 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003682 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003683 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003684 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003687 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003688 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003689 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003690 else if (!strcmp(args[1], "originalto")) {
3691 int cur_arg;
3692
3693 /* insert x-original-to field, but not for the IP address listed as an except.
3694 * set default options (ie: bitfield, header name, etc)
3695 */
3696
3697 curproxy->options |= PR_O_ORGTO;
3698
3699 free(curproxy->orgto_hdr_name);
3700 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3701 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3702
Willy Tarreau87cf5142011-08-19 22:57:24 +02003703 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003704 cur_arg = 2;
3705 while (*(args[cur_arg])) {
3706 if (!strcmp(args[cur_arg], "except")) {
3707 /* suboption except - needs additional argument for it */
3708 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3709 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3710 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003713 }
3714 /* flush useless bits */
3715 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3716 cur_arg += 2;
3717 } else if (!strcmp(args[cur_arg], "header")) {
3718 /* suboption header - needs additional argument for it */
3719 if (*(args[cur_arg+1]) == 0) {
3720 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3721 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003724 }
3725 free(curproxy->orgto_hdr_name);
3726 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3727 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3728 cur_arg += 2;
3729 } else {
3730 /* unknown suboption - catchall */
3731 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3732 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003735 }
3736 } /* end while loop */
3737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 else {
3739 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreau93893792009-07-23 13:19:11 +02003743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003745 else if (!strcmp(args[0], "default_backend")) {
3746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003748
3749 if (*(args[1]) == 0) {
3750 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003753 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003754 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003755 curproxy->defbe.name = strdup(args[1]);
3756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003760
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003761 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 /* enable reconnections to dispatch */
3765 curproxy->options |= PR_O_REDISP;
3766 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003767 else if (!strcmp(args[0], "http-check")) {
3768 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003770
3771 if (strcmp(args[1], "disable-on-404") == 0) {
3772 /* enable a graceful server shutdown on an HTTP 404 response */
3773 curproxy->options |= PR_O_DISABLE404;
3774 }
Willy Tarreauef781042010-01-27 11:53:01 +01003775 else if (strcmp(args[1], "send-state") == 0) {
3776 /* enable emission of the apparent state of a server in HTTP checks */
3777 curproxy->options2 |= PR_O2_CHK_SNDST;
3778 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003779 else if (strcmp(args[1], "expect") == 0) {
3780 const char *ptr_arg;
3781 int cur_arg;
3782
3783 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3784 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
3787 }
3788
3789 cur_arg = 2;
3790 /* consider exclamation marks, sole or at the beginning of a word */
3791 while (*(ptr_arg = args[cur_arg])) {
3792 while (*ptr_arg == '!') {
3793 curproxy->options2 ^= PR_O2_EXP_INV;
3794 ptr_arg++;
3795 }
3796 if (*ptr_arg)
3797 break;
3798 cur_arg++;
3799 }
3800 /* now ptr_arg points to the beginning of a word past any possible
3801 * exclamation mark, and cur_arg is the argument which holds this word.
3802 */
3803 if (strcmp(ptr_arg, "status") == 0) {
3804 if (!*(args[cur_arg + 1])) {
3805 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3806 file, linenum, args[0], args[1], ptr_arg);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003811 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003812 curproxy->expect_str = strdup(args[cur_arg + 1]);
3813 }
3814 else if (strcmp(ptr_arg, "string") == 0) {
3815 if (!*(args[cur_arg + 1])) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3817 file, linenum, args[0], args[1], ptr_arg);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
3821 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003822 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003823 curproxy->expect_str = strdup(args[cur_arg + 1]);
3824 }
3825 else if (strcmp(ptr_arg, "rstatus") == 0) {
3826 if (!*(args[cur_arg + 1])) {
3827 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3828 file, linenum, args[0], args[1], ptr_arg);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003833 free(curproxy->expect_str);
3834 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3835 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003836 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3837 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3838 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3839 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 }
3844 else if (strcmp(ptr_arg, "rstring") == 0) {
3845 if (!*(args[cur_arg + 1])) {
3846 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3847 file, linenum, args[0], args[1], ptr_arg);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003852 free(curproxy->expect_str);
3853 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3854 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003855 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3856 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3857 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3858 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
3862 }
3863 else {
3864 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3865 file, linenum, args[0], args[1], ptr_arg);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003870 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003871 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 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003874 }
3875 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003876 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003877 if (curproxy == &defproxy) {
3878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003881 }
3882
Willy Tarreaub80c2302007-11-30 20:51:32 +01003883 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003885
3886 if (strcmp(args[1], "fail") == 0) {
3887 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003888 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003889 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003893 }
3894
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003895 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3896 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3897 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003900 }
3901 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3902 }
3903 else {
3904 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02003909#ifdef TPROXY
3910 else if (!strcmp(args[0], "transparent")) {
3911 /* enable transparent proxy connections */
3912 curproxy->options |= PR_O_TRANSP;
3913 }
3914#endif
3915 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003916 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003918
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 if (*(args[1]) == 0) {
3920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 }
3924 curproxy->maxconn = atol(args[1]);
3925 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003926 else if (!strcmp(args[0], "backlog")) { /* backlog */
3927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003929
3930 if (*(args[1]) == 0) {
3931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003934 }
3935 curproxy->backlog = atol(args[1]);
3936 }
Willy Tarreau86034312006-12-29 00:10:33 +01003937 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003940
Willy Tarreau86034312006-12-29 00:10:33 +01003941 if (*(args[1]) == 0) {
3942 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003945 }
3946 curproxy->fullconn = atol(args[1]);
3947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3949 if (*(args[1]) == 0) {
3950 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003954 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3955 if (err) {
3956 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3957 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003960 }
3961 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 }
3963 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003964 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003965 int port1, port2;
3966
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967 if (curproxy == &defproxy) {
3968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003972 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003974
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003975 sk = str2sa_range(args[1], &port1, &port2);
3976 if (!sk) {
3977 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n", file, linenum, args[0], args[1]);
3978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
3981
3982 if (port1 != port2) {
3983 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3984 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003988
3989 if (!port1) {
3990 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3991 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003995
Willy Tarreaud5191e72010-02-09 20:50:45 +01003996 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003997 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998 }
3999 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004002
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004003 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4004 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004009 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4010 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4011 err_code |= ERR_WARN;
4012
4013 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4014 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4015 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4016 }
4017 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4018 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4019 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4020 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004021 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4022 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4023 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4024 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004025 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004026 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
4029 }
4030 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004033 short realport = 0;
4034 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004041 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004042 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043
4044 if (!*args[2]) {
4045 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004050
4051 err = invalid_char(args[1]);
4052 if (err) {
4053 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4054 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004057 }
4058
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004059 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004060 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004061 int port1, port2;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004062
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004063 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4065 err_code |= ERR_ALERT | ERR_ABORT;
4066 goto out;
4067 }
4068
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004069 /* the servers are linked backwards first */
4070 newsrv->next = curproxy->srv;
4071 curproxy->srv = newsrv;
4072 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004073 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004074 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004076 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004077 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004078 LIST_INIT(&newsrv->pendconns);
4079 do_check = 0;
4080 newsrv->state = SRV_RUNNING; /* early server setup */
4081 newsrv->last_change = now.tv_sec;
4082 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004085 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004086 * - IP: => port=+0, relative
4087 * - IP:N => port=N, absolute
4088 * - IP:+N => port=+N, relative
4089 * - IP:-N => port=-N, relative
4090 */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004091 sk = str2sa_range(args[2], &port1, &port2);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004092 if (!sk) {
4093 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004097
4098 if (!port1 || !port2) {
4099 /* no port specified, +offset, -offset */
4100 newsrv->state |= SRV_MAPPORTS;
4101 }
4102 else if (port1 != port2) {
4103 /* port range */
4104 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4105 file, linenum, args[0], args[1], args[2]);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109 else {
4110 /* used by checks */
4111 realport = port1;
4112 }
4113
Willy Tarreaud5191e72010-02-09 20:50:45 +01004114 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004115 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4116 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004117
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004118 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004119 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4120 file, linenum, newsrv->addr.ss_family, args[2]);
4121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
4123 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004124
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004125 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004126 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004127 newsrv->inter = curproxy->defsrv.inter;
4128 newsrv->fastinter = curproxy->defsrv.fastinter;
4129 newsrv->downinter = curproxy->defsrv.downinter;
4130 newsrv->rise = curproxy->defsrv.rise;
4131 newsrv->fall = curproxy->defsrv.fall;
4132 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4133 newsrv->minconn = curproxy->defsrv.minconn;
4134 newsrv->maxconn = curproxy->defsrv.maxconn;
4135 newsrv->slowstart = curproxy->defsrv.slowstart;
4136 newsrv->onerror = curproxy->defsrv.onerror;
4137 newsrv->consecutive_errors_limit
4138 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004139#ifdef OPENSSL
4140 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4141#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004142 newsrv->uweight = newsrv->iweight
4143 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004145 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004147 cur_arg = 3;
4148 } else {
4149 newsrv = &curproxy->defsrv;
4150 cur_arg = 1;
4151 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004152
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004154 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 newsrv->cookie = strdup(args[cur_arg + 1]);
4156 newsrv->cklen = strlen(args[cur_arg + 1]);
4157 cur_arg += 2;
4158 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004159 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004160 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4161 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004164 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004165 if (!*args[cur_arg + 1]) {
4166 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4167 file, linenum, args[cur_arg]);
4168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
4170 }
4171
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004173 if (newsrv->rise <= 0) {
4174 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4175 file, linenum, args[cur_arg]);
4176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
4178 }
4179
Willy Tarreau96839092010-03-29 10:02:24 +02004180 if (newsrv->health)
4181 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 cur_arg += 2;
4183 }
4184 else if (!strcmp(args[cur_arg], "fall")) {
4185 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004186
4187 if (!*args[cur_arg + 1]) {
4188 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4189 file, linenum, args[cur_arg]);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192 }
4193
4194 if (newsrv->fall <= 0) {
4195 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4196 file, linenum, args[cur_arg]);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
4199 }
4200
Willy Tarreaubaaee002006-06-26 02:48:02 +02004201 cur_arg += 2;
4202 }
4203 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004204 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4205 if (err) {
4206 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4207 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004210 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004211 if (val <= 0) {
4212 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4213 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004216 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004217 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 cur_arg += 2;
4219 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004220 else if (!strcmp(args[cur_arg], "fastinter")) {
4221 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4222 if (err) {
4223 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4224 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004227 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004228 if (val <= 0) {
4229 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4230 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004233 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004234 newsrv->fastinter = val;
4235 cur_arg += 2;
4236 }
4237 else if (!strcmp(args[cur_arg], "downinter")) {
4238 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4239 if (err) {
4240 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4241 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004244 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004245 if (val <= 0) {
4246 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4247 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004250 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004251 newsrv->downinter = val;
4252 cur_arg += 2;
4253 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004254 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004255 struct sockaddr_storage *sk;
4256 int port1, port2;
4257
4258 sk = str2sa_range(args[cur_arg + 1], &port1, &port2);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004259 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004260 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4261 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004265 if (port1 != port2) {
4266 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4267 file, linenum, args[cur_arg], args[cur_arg + 1]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004272 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004273 cur_arg += 2;
4274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004275 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004276 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 cur_arg += 2;
4278 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004279 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 newsrv->state |= SRV_BACKUP;
4281 cur_arg ++;
4282 }
Simon Hormanfa461682011-06-25 09:39:49 +09004283 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4284 newsrv->state |= SRV_NON_STICK;
4285 cur_arg ++;
4286 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004287 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4288 newsrv->state |= SRV_SEND_PROXY;
4289 cur_arg ++;
4290 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004291 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4292 newsrv->check.send_proxy = 1;
4293 cur_arg ++;
4294 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 else if (!strcmp(args[cur_arg], "weight")) {
4296 int w;
4297 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004298 if (w < 0 || w > 256) {
4299 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004304 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 cur_arg += 2;
4306 }
4307 else if (!strcmp(args[cur_arg], "minconn")) {
4308 newsrv->minconn = atol(args[cur_arg + 1]);
4309 cur_arg += 2;
4310 }
4311 else if (!strcmp(args[cur_arg], "maxconn")) {
4312 newsrv->maxconn = atol(args[cur_arg + 1]);
4313 cur_arg += 2;
4314 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004315 else if (!strcmp(args[cur_arg], "maxqueue")) {
4316 newsrv->maxqueue = atol(args[cur_arg + 1]);
4317 cur_arg += 2;
4318 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004319 else if (!strcmp(args[cur_arg], "slowstart")) {
4320 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004321 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004322 if (err) {
4323 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4324 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004327 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004328 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004329 cur_arg += 2;
4330 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004331 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004332
4333 if (!*args[cur_arg + 1]) {
4334 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4335 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004338 }
4339
4340 newsrv->trackit = strdup(args[cur_arg + 1]);
4341
4342 cur_arg += 2;
4343 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004344 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004345 global.maxsock++;
4346 do_check = 1;
4347 cur_arg += 1;
4348 }
Willy Tarreau96839092010-03-29 10:02:24 +02004349 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4350 newsrv->state |= SRV_MAINTAIN;
4351 newsrv->state &= ~SRV_RUNNING;
4352 newsrv->health = 0;
4353 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004354 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004355 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004356 if (!strcmp(args[cur_arg + 1], "none"))
4357 newsrv->observe = HANA_OBS_NONE;
4358 else if (!strcmp(args[cur_arg + 1], "layer4"))
4359 newsrv->observe = HANA_OBS_LAYER4;
4360 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4361 if (curproxy->mode != PR_MODE_HTTP) {
4362 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4363 file, linenum, args[cur_arg + 1]);
4364 err_code |= ERR_ALERT;
4365 }
4366 newsrv->observe = HANA_OBS_LAYER7;
4367 }
4368 else {
4369 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004370 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004371 file, linenum, args[cur_arg], args[cur_arg + 1]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
4376 cur_arg += 2;
4377 }
4378 else if (!strcmp(args[cur_arg], "on-error")) {
4379 if (!strcmp(args[cur_arg + 1], "fastinter"))
4380 newsrv->onerror = HANA_ONERR_FASTINTER;
4381 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4382 newsrv->onerror = HANA_ONERR_FAILCHK;
4383 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4384 newsrv->onerror = HANA_ONERR_SUDDTH;
4385 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4386 newsrv->onerror = HANA_ONERR_MARKDWN;
4387 else {
4388 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004389 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004390 file, linenum, args[cur_arg], args[cur_arg + 1]);
4391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
4393 }
4394
4395 cur_arg += 2;
4396 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004397 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4398 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4399 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4400 else {
4401 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4402 file, linenum, args[cur_arg], args[cur_arg + 1]);
4403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
4405 }
4406
4407 cur_arg += 2;
4408 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004409 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4410 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4411 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4412 else {
4413 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4414 file, linenum, args[cur_arg], args[cur_arg + 1]);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418
4419 cur_arg += 2;
4420 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004421 else if (!strcmp(args[cur_arg], "error-limit")) {
4422 if (!*args[cur_arg + 1]) {
4423 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4424 file, linenum, args[cur_arg]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428
4429 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4430
4431 if (newsrv->consecutive_errors_limit <= 0) {
4432 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4433 file, linenum, args[cur_arg]);
4434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004437 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004438 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004439 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004440 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004441 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004442
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004444 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4445 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004449 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004450 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4451 if (!sk) {
4452 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
4455 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004456 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004457
4458 if (port_low != port_high) {
4459 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004460
4461 if (!port_low || !port_high) {
4462 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4463 file, linenum, args[cur_arg], args[cur_arg + 1]);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 }
4467
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004468 if (port_low <= 0 || port_low > 65535 ||
4469 port_high <= 0 || port_high > 65535 ||
4470 port_low > port_high) {
4471 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4472 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004475 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004476 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4477 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4478 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004479 }
4480
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004482 while (*(args[cur_arg])) {
4483 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004484#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4485#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004486 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4488 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004491 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004492#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004493 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004494 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004495 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004498 }
4499 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004500 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4501 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004502 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004503 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4504 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004505 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4506 char *name, *end;
4507
4508 name = args[cur_arg+1] + 7;
4509 while (isspace(*name))
4510 name++;
4511
4512 end = name;
4513 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4514 end++;
4515
Willy Tarreauef9a3602012-12-08 22:29:20 +01004516 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4517 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4518 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4519 newsrv->conn_src.bind_hdr_len = end - name;
4520 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4521 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4522 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004523
4524 /* now look for an occurrence number */
4525 while (isspace(*end))
4526 end++;
4527 if (*end == ',') {
4528 end++;
4529 name = end;
4530 if (*end == '-')
4531 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004532 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004533 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004534 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004535 }
4536
Willy Tarreauef9a3602012-12-08 22:29:20 +01004537 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004538 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4539 " occurrences values smaller than %d.\n",
4540 file, linenum, MAX_HDR_HISTORY);
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004544 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004545 struct sockaddr_storage *sk;
4546 int port1, port2;
4547
4548 sk = str2sa_range(args[cur_arg + 1], &port1, &port2);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004550 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4551 file, linenum, args[cur_arg], args[cur_arg + 1]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555 if (port1 != port2) {
4556 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4557 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
4560 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004561 newsrv->conn_src.tproxy_addr = *sk;
4562 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004563 }
4564 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004565#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004566 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004567#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004568 cur_arg += 2;
4569 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004570#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004571 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004572 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004575#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4576 } /* "usesrc" */
4577
4578 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4579#ifdef SO_BINDTODEVICE
4580 if (!*args[cur_arg + 1]) {
4581 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004585 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004586 free(newsrv->conn_src.iface_name);
4587 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4588 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004589 global.last_checks |= LSTCHK_NETADM;
4590#else
4591 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4592 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004595#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004596 cur_arg += 2;
4597 continue;
4598 }
4599 /* this keyword in not an option of "source" */
4600 break;
4601 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004603 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004604 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4605 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004610 static int srv_dumped;
4611 struct srv_kw *kw;
4612 char *err;
4613
4614 kw = srv_find_kw(args[cur_arg]);
4615 if (kw) {
4616 char *err = NULL;
4617 int code;
4618
4619 if (!kw->parse) {
4620 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4621 file, linenum, args[0], args[1], args[cur_arg]);
4622 cur_arg += 1 + kw->skip ;
4623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
4625 }
4626
4627 if (defsrv && !kw->default_ok) {
4628 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4629 file, linenum, args[0], args[1], args[cur_arg]);
4630 cur_arg += 1 + kw->skip ;
4631 err_code |= ERR_ALERT;
4632 continue;
4633 }
4634
4635 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4636 err_code |= code;
4637
4638 if (code) {
4639 if (err && *err) {
4640 indent_msg(&err, 2);
4641 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4642 }
4643 else
4644 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4645 file, linenum, args[0], args[1], args[cur_arg]);
4646 if (code & ERR_FATAL) {
4647 free(err);
4648 cur_arg += 1 + kw->skip;
4649 goto out;
4650 }
4651 }
4652 free(err);
4653 cur_arg += 1 + kw->skip;
4654 continue;
4655 }
4656
4657 err = NULL;
4658 if (!srv_dumped) {
4659 srv_dump_kws(&err);
4660 indent_msg(&err, 4);
4661 srv_dumped = 1;
4662 }
4663
4664 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4665 file, linenum, args[0], args[1], args[cur_arg],
4666 err ? " Registered keywords :" : "", err ? err : "");
4667 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004668
Willy Tarreau93893792009-07-23 13:19:11 +02004669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004671 }
4672 }
4673
4674 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004675 if (newsrv->trackit) {
4676 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4677 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004680 }
4681
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004682 /* If neither a port nor an addr was specified and no check transport
4683 * layer is forced, then the transport layer used by the checks is the
4684 * same as for the production traffic. Otherwise we use raw_sock by
4685 * default, unless one is specified.
4686 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004687 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004688#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004689 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004690#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004691 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4692 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004693 /* try to get the port from check.addr if check.port not set */
4694 if (!newsrv->check.port)
4695 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004696
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004697 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004698 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004699
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004700 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004701 /* not yet valid, because no port was set on
4702 * the server either. We'll check if we have
4703 * a known port on the first listener.
4704 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004705 struct listener *l;
4706
4707 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004708 newsrv->check.port = get_host_port(&l->addr);
4709 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004710 break;
4711 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004712 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004713 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4715 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004719
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004720 /* Allocate buffer for check requests... */
4721 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004722 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4723 err_code |= ERR_ALERT | ERR_ABORT;
4724 goto out;
4725 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004726 newsrv->check.bi->size = global.tune.chksize;
4727
4728 /* Allocate buffer for check responses... */
4729 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4730 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4731 err_code |= ERR_ALERT | ERR_ABORT;
4732 goto out;
4733 }
4734 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004735
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004736 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004737 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004738 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4739 err_code |= ERR_ALERT | ERR_ABORT;
4740 goto out;
4741 }
4742
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004743 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4744 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 newsrv->state |= SRV_CHECKED;
4746 }
4747
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004748 if (!defsrv) {
4749 if (newsrv->state & SRV_BACKUP)
4750 curproxy->srv_bck++;
4751 else
4752 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004753
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004754 newsrv->prev_state = newsrv->state;
4755 }
William Lallemanda73203e2012-03-12 12:48:57 +01004756 }
4757
4758 else if (strcmp(args[0], "unique-id-format") == 0) {
4759 if (!*(args[1])) {
4760 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
4763 }
William Lallemand3203ff42012-11-11 17:30:56 +01004764 if (*(args[2])) {
4765 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
4768 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004769 free(curproxy->uniqueid_format_string);
4770 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004771 }
William Lallemanda73203e2012-03-12 12:48:57 +01004772
4773 else if (strcmp(args[0], "unique-id-header") == 0) {
4774 if (!*(args[1])) {
4775 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
4778 }
4779 free(curproxy->header_unique_id);
4780 curproxy->header_unique_id = strdup(args[1]);
4781 }
4782
William Lallemand723b73a2012-02-08 16:37:49 +01004783 else if (strcmp(args[0], "log-format") == 0) {
4784 if (!*(args[1])) {
4785 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788 }
William Lallemand3203ff42012-11-11 17:30:56 +01004789 if (*(args[2])) {
4790 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
4793 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004794
4795 if (curproxy->logformat_string != default_http_log_format &&
4796 curproxy->logformat_string != default_tcp_log_format &&
4797 curproxy->logformat_string != clf_http_log_format)
4798 free(curproxy->logformat_string);
4799 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 }
William Lallemand723b73a2012-02-08 16:37:49 +01004801
William Lallemand0f99e342011-10-12 17:50:54 +02004802 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4803 /* delete previous herited or defined syslog servers */
4804 struct logsrv *back;
4805
4806 if (*(args[1]) != 0) {
4807 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
4811
William Lallemand723b73a2012-02-08 16:37:49 +01004812 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4813 LIST_DEL(&tmplogsrv->list);
4814 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004815 }
4816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004818 struct logsrv *logsrv;
4819
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004821 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004822 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004823 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004824 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004825 LIST_INIT(&node->list);
4826 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004830
4831 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832
William Lallemand0f99e342011-10-12 17:50:54 +02004833 logsrv->facility = get_log_facility(args[2]);
4834 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 }
4840
William Lallemand0f99e342011-10-12 17:50:54 +02004841 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004843 logsrv->level = get_log_level(args[3]);
4844 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
4848
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
4850 }
4851
William Lallemand0f99e342011-10-12 17:50:54 +02004852 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004853 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004854 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004855 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004856 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004860 }
4861 }
4862
Robert Tsai81ae1952007-12-05 10:47:29 +01004863 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004864 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004865 if (!sk) {
4866 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004867 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
William Lallemand0f99e342011-10-12 17:50:54 +02004871 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004872 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004873 struct sockaddr_storage *sk;
4874 int port1, port2;
4875
4876 sk = str2sa_range(args[1], &port1, &port2);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004877 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004878 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4879 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004883
4884 if (port1 != port2) {
4885 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4886 file, linenum, args[0], args[1]);
4887 err_code |= ERR_ALERT | ERR_FATAL;
4888 goto out;
4889 }
4890
William Lallemand0f99e342011-10-12 17:50:54 +02004891 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004892 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004893 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
William Lallemand0f99e342011-10-12 17:50:54 +02004895
4896 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
4898 else {
4899 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4900 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904 }
4905 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004906 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004907 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004908 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004909
Willy Tarreau977b8e42006-12-29 14:19:17 +01004910 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004911 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004912
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004914 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4915 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004916 err_code |= ERR_ALERT | ERR_FATAL;
4917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004919
4920 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004921 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4922 free(curproxy->conn_src.iface_name);
4923 curproxy->conn_src.iface_name = NULL;
4924 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004925
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004926 sk = str2sa_range(args[1], &port1, &port2);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004927 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004928 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4929 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004933
4934 if (port1 != port2) {
4935 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4936 file, linenum, args[0], args[1]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
4940
Willy Tarreauef9a3602012-12-08 22:29:20 +01004941 curproxy->conn_src.source_addr = *sk;
4942 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004943
4944 cur_arg = 2;
4945 while (*(args[cur_arg])) {
4946 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004947#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4948#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004949 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004950 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4951 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004954 }
4955#endif
4956 if (!*args[cur_arg + 1]) {
4957 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4958 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004961 }
4962
4963 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004964 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4965 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004966 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004967 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4968 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004969 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4970 char *name, *end;
4971
4972 name = args[cur_arg+1] + 7;
4973 while (isspace(*name))
4974 name++;
4975
4976 end = name;
4977 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4978 end++;
4979
Willy Tarreauef9a3602012-12-08 22:29:20 +01004980 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4981 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4982 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4983 curproxy->conn_src.bind_hdr_len = end - name;
4984 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4985 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4986 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004987
4988 /* now look for an occurrence number */
4989 while (isspace(*end))
4990 end++;
4991 if (*end == ',') {
4992 end++;
4993 name = end;
4994 if (*end == '-')
4995 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004996 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004997 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004998 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004999 }
5000
Willy Tarreauef9a3602012-12-08 22:29:20 +01005001 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005002 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5003 " occurrences values smaller than %d.\n",
5004 file, linenum, MAX_HDR_HISTORY);
5005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
5007 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005008 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005009 struct sockaddr_storage *sk = str2sa_range(args[cur_arg + 1], &port1, &port2);
5010
Willy Tarreaud5191e72010-02-09 20:50:45 +01005011 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005012 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
5013 file, linenum, args[cur_arg], args[cur_arg + 1]);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
5017 if (port1 != port2) {
5018 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5019 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
5022 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005023 curproxy->conn_src.tproxy_addr = *sk;
5024 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005025 }
5026 global.last_checks |= LSTCHK_NETADM;
5027#if !defined(CONFIG_HAP_LINUX_TPROXY)
5028 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005029#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005030#else /* no TPROXY support */
5031 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005032 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005035#endif
5036 cur_arg += 2;
5037 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005038 }
5039
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005040 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5041#ifdef SO_BINDTODEVICE
5042 if (!*args[cur_arg + 1]) {
5043 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005047 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005048 free(curproxy->conn_src.iface_name);
5049 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5050 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005051 global.last_checks |= LSTCHK_NETADM;
5052#else
5053 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5054 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005057#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005058 cur_arg += 2;
5059 continue;
5060 }
5061 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005062 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005067 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5068 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5069 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005074 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5076 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080
5081 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005082 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005083 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005084 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 }
5087 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005088 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005089 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005090 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
5094 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005095 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005096 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005097 args[0], args[1], NULL, (const char **)args+2);
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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005115 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005121 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005122 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005125 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005127 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005128 }
5129 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
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_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005132 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5139 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143
5144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005145 SMP_OPT_DIR_REQ, ACT_REPLACE, 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 Tarreaubaaee002006-06-26 02:48:02 +02005149 }
5150 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005152 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005153 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
5157 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005159 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005160 args[0], args[1], NULL, (const char **)args+2);
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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqiallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005178 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005186 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005187
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 if (curproxy == &defproxy) {
5189 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005193 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005195
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 if (*(args[1]) == 0) {
5197 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005201
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005202 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005203 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5204 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5205 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5210 }
5211 else if (*args[2]) {
5212 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5213 file, linenum, args[0], args[2]);
5214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005218 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005219 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005220 wl->s = strdup(args[1]);
5221 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005222 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
5224 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5227 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005231
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005234 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
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_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005248 args[0], args[1], NULL, (const char **)args+2);
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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259
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_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005262 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005269 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
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_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005276 args[0], args[1], NULL, (const char **)args+2);
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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005281 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005282
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 if (curproxy == &defproxy) {
5284 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005288 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 if (*(args[1]) == 0) {
5292 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005297 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005298 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5299 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5300 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
5303 }
5304 err_code |= warnif_cond_requires_req(cond, file, linenum);
5305 }
5306 else if (*args[2]) {
5307 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5308 file, linenum, args[0], args[2]);
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005313 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005314 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005315 wl->s = strdup(args[1]);
5316 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 }
5318 else if (!strcmp(args[0], "errorloc") ||
5319 !strcmp(args[0], "errorloc302") ||
5320 !strcmp(args[0], "errorloc303")) { /* error location */
5321 int errnum, errlen;
5322 char *err;
5323
Willy Tarreau977b8e42006-12-29 14:19:17 +01005324 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005325 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005326
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005328 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
5332
5333 errnum = atol(args[1]);
5334 if (!strcmp(args[0], "errorloc303")) {
5335 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5336 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5337 } else {
5338 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5339 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5340 }
5341
Willy Tarreau0f772532006-12-23 20:51:41 +01005342 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5343 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005344 chunk_destroy(&curproxy->errmsg[rc]);
5345 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005346 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005349
5350 if (rc >= HTTP_ERR_SIZE) {
5351 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5352 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 free(err);
5354 }
5355 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005356 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5357 int errnum, errlen, fd;
5358 char *err;
5359 struct stat stat;
5360
5361 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005363
5364 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005365 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005368 }
5369
5370 fd = open(args[2], O_RDONLY);
5371 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5372 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5373 file, linenum, args[2], args[1]);
5374 if (fd >= 0)
5375 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
5377 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005378 }
5379
Willy Tarreau27a674e2009-08-17 07:23:33 +02005380 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005381 errlen = stat.st_size;
5382 } else {
5383 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005384 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005385 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005386 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005387 }
5388
5389 err = malloc(errlen); /* malloc() must succeed during parsing */
5390 errnum = read(fd, err, errlen);
5391 if (errnum != errlen) {
5392 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5393 file, linenum, args[2], args[1]);
5394 close(fd);
5395 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005398 }
5399 close(fd);
5400
5401 errnum = atol(args[1]);
5402 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5403 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005404 chunk_destroy(&curproxy->errmsg[rc]);
5405 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005406 break;
5407 }
5408 }
5409
5410 if (rc >= HTTP_ERR_SIZE) {
5411 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5412 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005414 free(err);
5415 }
5416 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005417 else if (!strcmp(args[0], "compression")) {
5418 struct comp *comp;
5419 if (curproxy->comp == NULL) {
5420 comp = calloc(1, sizeof(struct comp));
5421 curproxy->comp = comp;
5422 } else {
5423 comp = curproxy->comp;
5424 }
5425
5426 if (!strcmp(args[1], "algo")) {
5427 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005428 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005429
William Lallemand82fe75c2012-10-23 10:25:10 +02005430 cur_arg = 2;
5431 if (!*args[cur_arg]) {
5432 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5433 file, linenum, args[0]);
5434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 while (*(args[cur_arg])) {
5438 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5439 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5440 file, linenum, args[0], args[cur_arg]);
5441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
5443 }
William Lallemand552df672012-11-07 13:21:47 +01005444 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5445 curproxy->comp->algos->end(&ctx);
5446 } else {
5447 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5448 file, linenum, args[0], args[cur_arg]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005452 cur_arg ++;
5453 continue;
5454 }
5455 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005456 else if (!strcmp(args[1], "offload")) {
5457 comp->offload = 1;
5458 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005459 else if (!strcmp(args[1], "type")) {
5460 int cur_arg;
5461 cur_arg = 2;
5462 if (!*args[cur_arg]) {
5463 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5464 file, linenum, args[0]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
5468 while (*(args[cur_arg])) {
5469 comp_append_type(comp, args[cur_arg]);
5470 cur_arg ++;
5471 continue;
5472 }
5473 }
5474 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005475 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005476 file, linenum, args[0]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005482 struct cfg_kw_list *kwl;
5483 int index;
5484
5485 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5486 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5487 if (kwl->kw[index].section != CFG_LISTEN)
5488 continue;
5489 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5490 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005491 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005492 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005493 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005496 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005497 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005498 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005499 err_code |= ERR_WARN;
5500 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005501 }
Willy Tarreau93893792009-07-23 13:19:11 +02005502 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005503 }
5504 }
5505 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005506
Willy Tarreau6daf3432008-01-22 16:44:08 +01005507 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
Willy Tarreau93893792009-07-23 13:19:11 +02005511 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005512 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005513 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514}
5515
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005516int
5517cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5518{
5519
5520 int err_code = 0;
5521 const char *err;
5522
5523 if (!strcmp(args[0], "userlist")) { /* new userlist */
5524 struct userlist *newul;
5525
5526 if (!*args[1]) {
5527 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5528 file, linenum, args[0]);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 }
5532
5533 err = invalid_char(args[1]);
5534 if (err) {
5535 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5536 file, linenum, *err, args[0], args[1]);
5537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
5539 }
5540
5541 for (newul = userlist; newul; newul = newul->next)
5542 if (!strcmp(newul->name, args[1])) {
5543 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5544 file, linenum, args[1]);
5545 err_code |= ERR_WARN;
5546 goto out;
5547 }
5548
5549 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5550 if (!newul) {
5551 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5552 err_code |= ERR_ALERT | ERR_ABORT;
5553 goto out;
5554 }
5555
5556 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5557 newul->name = strdup(args[1]);
5558
5559 if (!newul->groupusers | !newul->name) {
5560 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5561 err_code |= ERR_ALERT | ERR_ABORT;
5562 goto out;
5563 }
5564
5565 newul->next = userlist;
5566 userlist = newul;
5567
5568 } else if (!strcmp(args[0], "group")) { /* new group */
5569 int cur_arg, i;
5570 const char *err;
5571
5572 if (!*args[1]) {
5573 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5574 file, linenum, args[0]);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 }
5578
5579 err = invalid_char(args[1]);
5580 if (err) {
5581 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5582 file, linenum, *err, args[0], args[1]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586
5587 for(i = 0; i < userlist->grpcnt; i++)
5588 if (!strcmp(userlist->groups[i], args[1])) {
5589 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5590 file, linenum, args[1], userlist->name);
5591 err_code |= ERR_ALERT;
5592 goto out;
5593 }
5594
5595 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5596 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5597 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
5600 }
5601
5602 cur_arg = 2;
5603
5604 while (*args[cur_arg]) {
5605 if (!strcmp(args[cur_arg], "users")) {
5606 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5607 cur_arg += 2;
5608 continue;
5609 } else {
5610 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5611 file, linenum, args[0]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615 }
5616
5617 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5618 } else if (!strcmp(args[0], "user")) { /* new user */
5619 struct auth_users *newuser;
5620 int cur_arg;
5621
5622 if (!*args[1]) {
5623 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5624 file, linenum, args[0]);
5625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628
5629 for (newuser = userlist->users; newuser; newuser = newuser->next)
5630 if (!strcmp(newuser->user, args[1])) {
5631 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5632 file, linenum, args[1], userlist->name);
5633 err_code |= ERR_ALERT;
5634 goto out;
5635 }
5636
5637 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5638 if (!newuser) {
5639 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5640 err_code |= ERR_ALERT | ERR_ABORT;
5641 goto out;
5642 }
5643
5644 newuser->user = strdup(args[1]);
5645
5646 newuser->next = userlist->users;
5647 userlist->users = newuser;
5648
5649 cur_arg = 2;
5650
5651 while (*args[cur_arg]) {
5652 if (!strcmp(args[cur_arg], "password")) {
5653#ifndef CONFIG_HAP_CRYPT
5654 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5655 file, linenum);
5656 err_code |= ERR_ALERT;
5657#endif
5658 newuser->pass = strdup(args[cur_arg + 1]);
5659 cur_arg += 2;
5660 continue;
5661 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5662 newuser->pass = strdup(args[cur_arg + 1]);
5663 newuser->flags |= AU_O_INSECURE;
5664 cur_arg += 2;
5665 continue;
5666 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005667 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005668 cur_arg += 2;
5669 continue;
5670 } else {
5671 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5672 file, linenum, args[0]);
5673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
5675 }
5676 }
5677 } else {
5678 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 }
5681
5682out:
5683 return err_code;
5684}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685
5686/*
5687 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005688 * Returns the error code, 0 if OK, or any combination of :
5689 * - ERR_ABORT: must abort ASAP
5690 * - ERR_FATAL: we can continue parsing but not start the service
5691 * - ERR_WARN: a warning has been emitted
5692 * - ERR_ALERT: an alert has been emitted
5693 * Only the two first ones can stop processing, the two others are just
5694 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005696int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005698 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 FILE *f;
5700 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005702 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 if ((f=fopen(file,"r")) == NULL)
5705 return -1;
5706
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005707 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005708 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005709 char *end;
5710 char *args[MAX_LINE_ARGS + 1];
5711 char *line = thisline;
5712
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 linenum++;
5714
5715 end = line + strlen(line);
5716
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005717 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5718 /* Check if we reached the limit and the last char is not \n.
5719 * Watch out for the last line without the terminating '\n'!
5720 */
5721 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005722 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005723 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005724 }
5725
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005727 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 line++;
5729
5730 arg = 0;
5731 args[arg] = line;
5732
5733 while (*line && arg < MAX_LINE_ARGS) {
5734 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5735 * C equivalent value. Other combinations left unchanged (eg: \1).
5736 */
5737 if (*line == '\\') {
5738 int skip = 0;
5739 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5740 *line = line[1];
5741 skip = 1;
5742 }
5743 else if (line[1] == 'r') {
5744 *line = '\r';
5745 skip = 1;
5746 }
5747 else if (line[1] == 'n') {
5748 *line = '\n';
5749 skip = 1;
5750 }
5751 else if (line[1] == 't') {
5752 *line = '\t';
5753 skip = 1;
5754 }
5755 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 unsigned char hex1, hex2;
5758 hex1 = toupper(line[2]) - '0';
5759 hex2 = toupper(line[3]) - '0';
5760 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5761 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5762 *line = (hex1<<4) + hex2;
5763 skip = 3;
5764 }
5765 else {
5766 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 }
5769 }
5770 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005771 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 end -= skip;
5773 }
5774 line++;
5775 }
5776 else if (*line == '#' || *line == '\n' || *line == '\r') {
5777 /* end of string, end of loop */
5778 *line = 0;
5779 break;
5780 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005781 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005783 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005784 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 line++;
5786 args[++arg] = line;
5787 }
5788 else {
5789 line++;
5790 }
5791 }
5792
5793 /* empty line */
5794 if (!**args)
5795 continue;
5796
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005797 if (*line) {
5798 /* we had to stop due to too many args.
5799 * Let's terminate the string, print the offending part then cut the
5800 * last arg.
5801 */
5802 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5803 line++;
5804 *line = '\0';
5805
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005806 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005807 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005808 err_code |= ERR_ALERT | ERR_FATAL;
5809 args[arg] = line;
5810 }
5811
Willy Tarreau540abe42007-05-02 20:50:16 +02005812 /* zero out remaining args and ensure that at least one entry
5813 * is zeroed out.
5814 */
5815 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 args[arg] = line;
5817 }
5818
Willy Tarreau3842f002009-06-14 11:39:52 +02005819 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005820 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005821 char *tmp;
5822
Willy Tarreau3842f002009-06-14 11:39:52 +02005823 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005824 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005825 for (arg=0; *args[arg+1]; arg++)
5826 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005827 *tmp = '\0'; // fix the next arg to \0
5828 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005829 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005830 else if (!strcmp(args[0], "default")) {
5831 kwm = KWM_DEF;
5832 for (arg=0; *args[arg+1]; arg++)
5833 args[arg] = args[arg+1]; // shift args after inversion
5834 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005835
William Lallemand0f99e342011-10-12 17:50:54 +02005836 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5837 strcmp(args[0], "log") != 0) {
5838 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005839 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005840 }
5841
Willy Tarreau977b8e42006-12-29 14:19:17 +01005842 if (!strcmp(args[0], "listen") ||
5843 !strcmp(args[0], "frontend") ||
5844 !strcmp(args[0], "backend") ||
5845 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005846 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005848 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005849 cursection = strdup(args[0]);
5850 }
5851 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005853 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005854 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005855 }
5856 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005857 confsect = CFG_USERLIST;
5858 free(cursection);
5859 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005860 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005861 else if (!strcmp(args[0], "peers")) {
5862 confsect = CFG_PEERS;
5863 free(cursection);
5864 cursection = strdup(args[0]);
5865 }
5866
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 /* else it's a section keyword */
5868
5869 switch (confsect) {
5870 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005871 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 break;
5873 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005874 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005876 case CFG_USERLIST:
5877 err_code |= cfg_parse_users(file, linenum, args, kwm);
5878 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005879 case CFG_PEERS:
5880 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5881 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005883 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005884 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005886
5887 if (err_code & ERR_ABORT)
5888 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005890 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005891 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005893 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005894}
5895
Willy Tarreaubb925012009-07-23 13:36:36 +02005896/*
5897 * Returns the error code, 0 if OK, or any combination of :
5898 * - ERR_ABORT: must abort ASAP
5899 * - ERR_FATAL: we can continue parsing but not start the service
5900 * - ERR_WARN: a warning has been emitted
5901 * - ERR_ALERT: an alert has been emitted
5902 * Only the two first ones can stop processing, the two others are just
5903 * indicators.
5904 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005905int check_config_validity()
5906{
5907 int cfgerr = 0;
5908 struct proxy *curproxy = NULL;
5909 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005910 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005911 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005912 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005913 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005915 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 /*
5917 * Now, check for the integrity of all that we have collected.
5918 */
5919
5920 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005921 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922
Willy Tarreau193b8c62012-11-22 00:17:38 +01005923 if (!global.tune.max_http_hdr)
5924 global.tune.max_http_hdr = MAX_HTTP_HDR;
5925
5926 if (!global.tune.cookie_len)
5927 global.tune.cookie_len = CAPTURE_LEN;
5928
5929 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5930
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005931 /* first, we will invert the proxy list order */
5932 curproxy = NULL;
5933 while (proxy) {
5934 struct proxy *next;
5935
5936 next = proxy->next;
5937 proxy->next = curproxy;
5938 curproxy = proxy;
5939 if (!next)
5940 break;
5941 proxy = next;
5942 }
5943
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005945 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005946 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005947 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005948 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005949 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005950 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005951 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005952
Willy Tarreau050536d2012-10-04 08:47:34 +02005953 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005954 /* proxy ID not set, use automatic numbering with first
5955 * spare entry starting with next_pxid.
5956 */
5957 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5958 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5959 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005960 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005961 next_pxid++;
5962
Willy Tarreau55ea7572007-06-17 19:56:27 +02005963
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005965 /* ensure we don't keep listeners uselessly bound */
5966 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 curproxy = curproxy->next;
5968 continue;
5969 }
5970
Willy Tarreau16a21472012-11-19 12:39:59 +01005971 /* number of processes this proxy is bound to */
5972 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5973
Willy Tarreauff01a212009-03-15 13:46:16 +01005974 switch (curproxy->mode) {
5975 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005976 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005977 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005978 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5979 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005980 cfgerr++;
5981 }
5982
5983 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005984 Warning("config : servers will be ignored for %s '%s'.\n",
5985 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005986 break;
5987
5988 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005989 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005990 break;
5991
5992 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005993 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005994 break;
5995 }
5996
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005997 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005998 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005999 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006000 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6001 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006002 cfgerr++;
6003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006004#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006005 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006006 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6007 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006008 cfgerr++;
6009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006010#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006011 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006012 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6013 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006014 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006015 }
6016 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006017 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006018 /* If no LB algo is set in a backend, and we're not in
6019 * transparent mode, dispatch mode nor proxy mode, we
6020 * want to use balance roundrobin by default.
6021 */
6022 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6023 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006024 }
6025 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006026
Willy Tarreau1620ec32011-08-06 17:05:02 +02006027 if (curproxy->options & PR_O_DISPATCH)
6028 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6029 else if (curproxy->options & PR_O_HTTP_PROXY)
6030 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6031 else if (curproxy->options & PR_O_TRANSP)
6032 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006033
Willy Tarreau1620ec32011-08-06 17:05:02 +02006034 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6035 if (curproxy->options & PR_O_DISABLE404) {
6036 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6037 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6038 err_code |= ERR_WARN;
6039 curproxy->options &= ~PR_O_DISABLE404;
6040 }
6041 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6042 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6043 "send-state", proxy_type_str(curproxy), curproxy->id);
6044 err_code |= ERR_WARN;
6045 curproxy->options &= ~PR_O2_CHK_SNDST;
6046 }
Willy Tarreauef781042010-01-27 11:53:01 +01006047 }
6048
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006049 /* if a default backend was specified, let's find it */
6050 if (curproxy->defbe.name) {
6051 struct proxy *target;
6052
Alex Williams96532db2009-11-01 21:27:13 -05006053 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006054 if (!target) {
6055 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6056 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006057 cfgerr++;
6058 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006059 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6060 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006061 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006062 } else {
6063 free(curproxy->defbe.name);
6064 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006065 /* we force the backend to be present on at least all of
6066 * the frontend's processes.
6067 */
6068 target->bind_proc = curproxy->bind_proc ?
6069 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006070
6071 /* Emit a warning if this proxy also has some servers */
6072 if (curproxy->srv) {
6073 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6074 curproxy->id);
6075 err_code |= ERR_WARN;
6076 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 }
6078 }
6079
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006080 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006081 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6082 /* map jump target for ACT_SETBE in req_rep chain */
6083 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006084 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006085 struct proxy *target;
6086
Willy Tarreaua496b602006-12-17 23:15:24 +01006087 if (exp->action != ACT_SETBE)
6088 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006089
Alex Williams96532db2009-11-01 21:27:13 -05006090 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006091 if (!target) {
6092 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6093 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006094 cfgerr++;
6095 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006096 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6097 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006098 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006099 } else {
6100 free((void *)exp->replace);
6101 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006102 /* we force the backend to be present on at least all of
6103 * the frontend's processes.
6104 */
6105 target->bind_proc = curproxy->bind_proc ?
6106 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006107 }
6108 }
6109 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006110
6111 /* find the target proxy for 'use_backend' rules */
6112 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006113 struct proxy *target;
6114
Alex Williams96532db2009-11-01 21:27:13 -05006115 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006116
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006117 if (!target) {
6118 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6119 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006120 cfgerr++;
6121 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006122 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6123 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006124 cfgerr++;
6125 } else {
6126 free((void *)rule->be.name);
6127 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006128 /* we force the backend to be present on at least all of
6129 * the frontend's processes.
6130 */
6131 target->bind_proc = curproxy->bind_proc ?
6132 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006133 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006134 }
6135
6136 /* find the target proxy for 'use_backend' rules */
6137 list_for_each_entry(srule, &curproxy->server_rules, list) {
6138 struct server *target = findserver(curproxy, srule->srv.name);
6139
6140 if (!target) {
6141 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6142 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6143 cfgerr++;
6144 continue;
6145 }
6146 free((void *)srule->srv.name);
6147 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006148 }
6149
Emeric Brunb982a3d2010-01-04 15:45:53 +01006150 /* find the target table for 'stick' rules */
6151 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6152 struct proxy *target;
6153
Emeric Brun1d33b292010-01-04 15:47:17 +01006154 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6155 if (mrule->flags & STK_IS_STORE)
6156 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6157
Emeric Brunb982a3d2010-01-04 15:45:53 +01006158 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006159 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006160 else
6161 target = curproxy;
6162
6163 if (!target) {
6164 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6165 curproxy->id, mrule->table.name);
6166 cfgerr++;
6167 }
6168 else if (target->table.size == 0) {
6169 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6170 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6171 cfgerr++;
6172 }
Willy Tarreau12785782012-04-27 21:37:17 +02006173 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6174 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006175 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6176 cfgerr++;
6177 }
6178 else {
6179 free((void *)mrule->table.name);
6180 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006181 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006182 }
6183 }
6184
6185 /* find the target table for 'store response' rules */
6186 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6187 struct proxy *target;
6188
Emeric Brun1d33b292010-01-04 15:47:17 +01006189 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6190
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006192 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006193 else
6194 target = curproxy;
6195
6196 if (!target) {
6197 Alert("Proxy '%s': unable to find store table '%s'.\n",
6198 curproxy->id, mrule->table.name);
6199 cfgerr++;
6200 }
6201 else if (target->table.size == 0) {
6202 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6203 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6204 cfgerr++;
6205 }
Willy Tarreau12785782012-04-27 21:37:17 +02006206 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6207 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006208 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6209 cfgerr++;
6210 }
6211 else {
6212 free((void *)mrule->table.name);
6213 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006214 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006215 }
6216 }
6217
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006218 /* find the target table for 'tcp-request' layer 4 rules */
6219 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6220 struct proxy *target;
6221
Willy Tarreau56123282010-08-06 19:06:56 +02006222 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006223 continue;
6224
6225 if (trule->act_prm.trk_ctr.table.n)
6226 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6227 else
6228 target = curproxy;
6229
6230 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006231 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6232 curproxy->id, trule->act_prm.trk_ctr.table.n,
6233 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006234 cfgerr++;
6235 }
6236 else if (target->table.size == 0) {
6237 Alert("Proxy '%s': table '%s' used but not configured.\n",
6238 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6239 cfgerr++;
6240 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006241 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6242 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6243 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6244 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6245 cfgerr++;
6246 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006247 else {
6248 free(trule->act_prm.trk_ctr.table.n);
6249 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006250 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006251 * to pass a list of counters to track and allocate them right here using
6252 * stktable_alloc_data_type().
6253 */
6254 }
6255 }
6256
Willy Tarreaud1f96522010-08-03 19:34:32 +02006257 /* find the target table for 'tcp-request' layer 6 rules */
6258 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6259 struct proxy *target;
6260
Willy Tarreau56123282010-08-06 19:06:56 +02006261 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006262 continue;
6263
6264 if (trule->act_prm.trk_ctr.table.n)
6265 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6266 else
6267 target = curproxy;
6268
6269 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006270 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6271 curproxy->id, trule->act_prm.trk_ctr.table.n,
6272 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006273 cfgerr++;
6274 }
6275 else if (target->table.size == 0) {
6276 Alert("Proxy '%s': table '%s' used but not configured.\n",
6277 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6278 cfgerr++;
6279 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006280 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6281 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6282 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6283 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6284 cfgerr++;
6285 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006286 else {
6287 free(trule->act_prm.trk_ctr.table.n);
6288 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006289 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006290 * to pass a list of counters to track and allocate them right here using
6291 * stktable_alloc_data_type().
6292 */
6293 }
6294 }
6295
Emeric Brun32da3c42010-09-23 18:39:19 +02006296 if (curproxy->table.peers.name) {
6297 struct peers *curpeers = peers;
6298
6299 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6300 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6301 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006302 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006303 break;
6304 }
6305 }
6306
6307 if (!curpeers) {
6308 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6309 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006310 free((void *)curproxy->table.peers.name);
6311 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006312 cfgerr++;
6313 }
6314 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006315 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6316 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006317 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006318 cfgerr++;
6319 }
6320 }
6321
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006322 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006323 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006324 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6325 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6326 "proxy", curproxy->id);
6327 cfgerr++;
6328 goto out_uri_auth_compat;
6329 }
6330
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006331 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006332 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006333 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006334 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006335
Willy Tarreau95fa4692010-02-01 13:05:50 +01006336 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6337 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006338
6339 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006340 uri_auth_compat_req[i++] = "realm";
6341 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6342 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006343
Willy Tarreau95fa4692010-02-01 13:05:50 +01006344 uri_auth_compat_req[i++] = "unless";
6345 uri_auth_compat_req[i++] = "{";
6346 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6347 uri_auth_compat_req[i++] = "}";
6348 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006349
Willy Tarreauff011f22011-01-06 17:51:27 +01006350 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6351 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006352 cfgerr++;
6353 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006354 }
6355
Willy Tarreauff011f22011-01-06 17:51:27 +01006356 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006357
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006358 if (curproxy->uri_auth->auth_realm) {
6359 free(curproxy->uri_auth->auth_realm);
6360 curproxy->uri_auth->auth_realm = NULL;
6361 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006362
6363 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006364 }
6365out_uri_auth_compat:
6366
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006367 cfgerr += acl_find_targets(curproxy);
6368
Willy Tarreau2738a142006-07-08 17:28:09 +02006369 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006370 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006371 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006372 (!curproxy->timeout.connect ||
6373 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006374 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006375 " | While not properly invalid, you will certainly encounter various problems\n"
6376 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006377 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006378 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006379 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006380 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006381
Willy Tarreau1fa31262007-12-03 00:36:16 +01006382 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6383 * We must still support older configurations, so let's find out whether those
6384 * parameters have been set or must be copied from contimeouts.
6385 */
6386 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006387 if (!curproxy->timeout.tarpit ||
6388 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006389 /* tarpit timeout not set. We search in the following order:
6390 * default.tarpit, curr.connect, default.connect.
6391 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006392 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006393 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006394 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006395 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006396 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006397 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006398 }
6399 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006400 (!curproxy->timeout.queue ||
6401 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006402 /* queue timeout not set. We search in the following order:
6403 * default.queue, curr.connect, default.connect.
6404 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006405 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006406 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006407 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006408 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006409 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006410 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006411 }
6412 }
6413
Willy Tarreau1620ec32011-08-06 17:05:02 +02006414 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006415 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6416 curproxy->check_req = (char *)malloc(curproxy->check_len);
6417 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006418 }
6419
Willy Tarreau193b8c62012-11-22 00:17:38 +01006420 /* ensure that cookie capture length is not too large */
6421 if (curproxy->capture_len >= global.tune.cookie_len) {
6422 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6423 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6424 err_code |= ERR_WARN;
6425 curproxy->capture_len = global.tune.cookie_len - 1;
6426 }
6427
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006428 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006429 if (curproxy->nb_req_cap) {
6430 if (curproxy->mode == PR_MODE_HTTP) {
6431 curproxy->req_cap_pool = create_pool("ptrcap",
6432 curproxy->nb_req_cap * sizeof(char *),
6433 MEM_F_SHARED);
6434 } else {
6435 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6436 proxy_type_str(curproxy), curproxy->id);
6437 err_code |= ERR_WARN;
6438 curproxy->to_log &= ~LW_REQHDR;
6439 curproxy->nb_req_cap = 0;
6440 }
6441 }
6442
6443 if (curproxy->nb_rsp_cap) {
6444 if (curproxy->mode == PR_MODE_HTTP) {
6445 curproxy->rsp_cap_pool = create_pool("ptrcap",
6446 curproxy->nb_rsp_cap * sizeof(char *),
6447 MEM_F_SHARED);
6448 } else {
6449 Warning("config : 'capture response 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_rsp_cap = 0;
6454 }
6455 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006456
Willy Tarreau196729e2012-05-31 19:30:26 +02006457 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006458 if (!(curproxy->cap & PR_CAP_FE)) {
6459 if (curproxy->logformat_string != default_http_log_format &&
6460 curproxy->logformat_string != default_tcp_log_format &&
6461 curproxy->logformat_string != clf_http_log_format)
6462 free(curproxy->logformat_string);
6463 curproxy->logformat_string = NULL;
6464 }
6465
Willy Tarreau196729e2012-05-31 19:30:26 +02006466 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006467 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006468
6469 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006470 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006471
Willy Tarreaubaaee002006-06-26 02:48:02 +02006472 /* first, we will invert the servers list order */
6473 newsrv = NULL;
6474 while (curproxy->srv) {
6475 struct server *next;
6476
6477 next = curproxy->srv->next;
6478 curproxy->srv->next = newsrv;
6479 newsrv = curproxy->srv;
6480 if (!next)
6481 break;
6482 curproxy->srv = next;
6483 }
6484
Willy Tarreaudd701652010-05-25 23:03:02 +02006485 /* assign automatic UIDs to servers which don't have one yet */
6486 next_id = 1;
6487 newsrv = curproxy->srv;
6488 while (newsrv != NULL) {
6489 if (!newsrv->puid) {
6490 /* server ID not set, use automatic numbering with first
6491 * spare entry starting with next_svid.
6492 */
6493 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6494 newsrv->conf.id.key = newsrv->puid = next_id;
6495 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6496 }
6497 next_id++;
6498 newsrv = newsrv->next;
6499 }
6500
Willy Tarreau20697042007-11-15 23:26:18 +01006501 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006502 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503
Willy Tarreau62c3be22012-01-20 13:12:32 +01006504 /*
6505 * If this server supports a maxconn parameter, it needs a dedicated
6506 * tasks to fill the emptied slots when a connection leaves.
6507 * Also, resolve deferred tracking dependency if needed.
6508 */
6509 newsrv = curproxy->srv;
6510 while (newsrv != NULL) {
6511 if (newsrv->minconn > newsrv->maxconn) {
6512 /* Only 'minconn' was specified, or it was higher than or equal
6513 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6514 * this will avoid further useless expensive computations.
6515 */
6516 newsrv->maxconn = newsrv->minconn;
6517 } else if (newsrv->maxconn && !newsrv->minconn) {
6518 /* minconn was not specified, so we set it to maxconn */
6519 newsrv->minconn = newsrv->maxconn;
6520 }
6521
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006522#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006523 if (newsrv->use_ssl || newsrv->check.use_ssl)
6524 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006525#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006526
Willy Tarreau62c3be22012-01-20 13:12:32 +01006527 if (newsrv->trackit) {
6528 struct proxy *px;
6529 struct server *srv;
6530 char *pname, *sname;
6531
6532 pname = newsrv->trackit;
6533 sname = strrchr(pname, '/');
6534
6535 if (sname)
6536 *sname++ = '\0';
6537 else {
6538 sname = pname;
6539 pname = NULL;
6540 }
6541
6542 if (pname) {
6543 px = findproxy(pname, PR_CAP_BE);
6544 if (!px) {
6545 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6546 proxy_type_str(curproxy), curproxy->id,
6547 newsrv->id, pname);
6548 cfgerr++;
6549 goto next_srv;
6550 }
6551 } else
6552 px = curproxy;
6553
6554 srv = findserver(px, sname);
6555 if (!srv) {
6556 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6557 proxy_type_str(curproxy), curproxy->id,
6558 newsrv->id, sname);
6559 cfgerr++;
6560 goto next_srv;
6561 }
6562
6563 if (!(srv->state & SRV_CHECKED)) {
6564 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6565 "tracking as it does not have checks enabled.\n",
6566 proxy_type_str(curproxy), curproxy->id,
6567 newsrv->id, px->id, srv->id);
6568 cfgerr++;
6569 goto next_srv;
6570 }
6571
6572 if (curproxy != px &&
6573 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6574 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6575 "tracking: disable-on-404 option inconsistency.\n",
6576 proxy_type_str(curproxy), curproxy->id,
6577 newsrv->id, px->id, srv->id);
6578 cfgerr++;
6579 goto next_srv;
6580 }
6581
6582 /* if the other server is forced disabled, we have to do the same here */
6583 if (srv->state & SRV_MAINTAIN) {
6584 newsrv->state |= SRV_MAINTAIN;
6585 newsrv->state &= ~SRV_RUNNING;
6586 newsrv->health = 0;
6587 }
6588
6589 newsrv->track = srv;
6590 newsrv->tracknext = srv->tracknext;
6591 srv->tracknext = newsrv;
6592
6593 free(newsrv->trackit);
6594 newsrv->trackit = NULL;
6595 }
6596 next_srv:
6597 newsrv = newsrv->next;
6598 }
6599
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006600 /* We have to initialize the server lookup mechanism depending
6601 * on what LB algorithm was choosen.
6602 */
6603
6604 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6605 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6606 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006607 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6608 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6609 init_server_map(curproxy);
6610 } else {
6611 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6612 fwrr_init_server_groups(curproxy);
6613 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006614 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006615
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006616 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006617 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6618 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6619 fwlc_init_server_tree(curproxy);
6620 } else {
6621 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6622 fas_init_server_tree(curproxy);
6623 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006624 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006625
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006626 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006627 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6628 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6629 chash_init_server_tree(curproxy);
6630 } else {
6631 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6632 init_server_map(curproxy);
6633 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006634 break;
6635 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006636
6637 if (curproxy->options & PR_O_LOGASAP)
6638 curproxy->to_log &= ~LW_BYTES;
6639
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006640 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006641 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006642 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6643 proxy_type_str(curproxy), curproxy->id);
6644 err_code |= ERR_WARN;
6645 }
6646
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006647 if (curproxy->mode != PR_MODE_HTTP) {
6648 int optnum;
6649
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006650 if (curproxy->uri_auth) {
6651 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6652 proxy_type_str(curproxy), curproxy->id);
6653 err_code |= ERR_WARN;
6654 curproxy->uri_auth = NULL;
6655 }
6656
Willy Tarreau87cf5142011-08-19 22:57:24 +02006657 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006658 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6659 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6660 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006661 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006662 }
6663
6664 if (curproxy->options & PR_O_ORGTO) {
6665 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6666 "originalto", proxy_type_str(curproxy), curproxy->id);
6667 err_code |= ERR_WARN;
6668 curproxy->options &= ~PR_O_ORGTO;
6669 }
6670
6671 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6672 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6673 (curproxy->cap & cfg_opts[optnum].cap) &&
6674 (curproxy->options & cfg_opts[optnum].val)) {
6675 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6676 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6677 err_code |= ERR_WARN;
6678 curproxy->options &= ~cfg_opts[optnum].val;
6679 }
6680 }
6681
6682 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6683 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6684 (curproxy->cap & cfg_opts2[optnum].cap) &&
6685 (curproxy->options2 & cfg_opts2[optnum].val)) {
6686 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6687 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6688 err_code |= ERR_WARN;
6689 curproxy->options2 &= ~cfg_opts2[optnum].val;
6690 }
6691 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006692
Willy Tarreauefa5f512010-03-30 20:13:29 +02006693#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006694 if (curproxy->conn_src.bind_hdr_occ) {
6695 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006696 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006697 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006698 err_code |= ERR_WARN;
6699 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006700#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006701 }
6702
Willy Tarreaubaaee002006-06-26 02:48:02 +02006703 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006704 * ensure that we're not cross-dressing a TCP server into HTTP.
6705 */
6706 newsrv = curproxy->srv;
6707 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006708 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006709 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6710 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006711 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006712 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006713
Willy Tarreau0cec3312011-10-31 13:49:26 +01006714 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6715 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6716 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6717 err_code |= ERR_WARN;
6718 }
6719
Willy Tarreauefa5f512010-03-30 20:13:29 +02006720#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006721 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6722 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006723 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 +01006724 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006725 err_code |= ERR_WARN;
6726 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006727#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006728 newsrv = newsrv->next;
6729 }
6730
Willy Tarreauc1a21672009-08-16 22:37:44 +02006731 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006732 if (!curproxy->accept)
6733 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006734
Willy Tarreauc1a21672009-08-16 22:37:44 +02006735 if (curproxy->tcp_req.inspect_delay ||
6736 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006737 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006738
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006739 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006740 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006741 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006742 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006743
6744 /* both TCP and HTTP must check switching rules */
6745 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6746 }
6747
6748 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006749 if (curproxy->tcp_req.inspect_delay ||
6750 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6751 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6752
Emeric Brun97679e72010-09-23 17:56:44 +02006753 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6754 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6755
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006756 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006757 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006758 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006759 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006760
6761 /* If the backend does requires RDP cookie persistence, we have to
6762 * enable the corresponding analyser.
6763 */
6764 if (curproxy->options2 & PR_O2_RDPC_PRST)
6765 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6766 }
6767
Emeric Brunc52962f2012-11-15 18:28:02 +01006768#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006769 /* Configure SSL for each bind line.
6770 * Note: if configuration fails at some point, the ->ctx member
6771 * remains NULL so that listeners can later detach.
6772 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006773 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006774 if (!bind_conf->is_ssl) {
6775 if (bind_conf->default_ctx) {
6776 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6777 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6778 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006779 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006780 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006781 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006782 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006783 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006784 cfgerr++;
6785 continue;
6786 }
6787
Emeric Brun4b3091e2012-09-24 15:48:52 +02006788 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006789 Alert("Unable to allocate SSL session cache.\n");
6790 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006791 continue;
6792 }
6793
Emeric Brunfc0421f2012-09-07 17:30:07 +02006794 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006795 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006796 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006797#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006798
Willy Tarreaue6b98942007-10-29 01:09:36 +01006799 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006800 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006801 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006802 if (!listener->luid) {
6803 /* listener ID not set, use automatic numbering with first
6804 * spare entry starting with next_luid.
6805 */
6806 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6807 listener->conf.id.key = listener->luid = next_id;
6808 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006809 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006810 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006811
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006812 /* enable separate counters */
6813 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6814 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006815 if (!listener->name)
6816 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006817 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006818
Willy Tarreaue6b98942007-10-29 01:09:36 +01006819 if (curproxy->options & PR_O_TCP_NOLING)
6820 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006821 if (!listener->maxconn)
6822 listener->maxconn = curproxy->maxconn;
6823 if (!listener->backlog)
6824 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006825 if (!listener->maxaccept)
6826 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6827
6828 /* we want to have an optimal behaviour on single process mode to
6829 * maximize the work at once, but in multi-process we want to keep
6830 * some fairness between processes, so we target half of the max
6831 * number of events to be balanced over all the processes the proxy
6832 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6833 * used to disable the limit.
6834 */
6835 if (listener->maxaccept > 0) {
6836 if (nbproc > 1)
6837 listener->maxaccept = (listener->maxaccept + 1) / 2;
6838 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6839 }
6840
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006841 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006842 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006843 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006844 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006845
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006846 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6847 listener->options |= LI_O_TCP_RULES;
6848
Willy Tarreaude3041d2010-05-31 10:56:17 +02006849 if (curproxy->mon_mask.s_addr)
6850 listener->options |= LI_O_CHK_MONNET;
6851
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006852 /* smart accept mode is automatic in HTTP mode */
6853 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006854 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006855 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6856 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006857 }
6858
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006859 /* Release unused SSL configs */
6860 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6861 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006862 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006863#ifdef USE_OPENSSL
6864 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006865 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006866 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006867 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006868 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006869#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006870 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006871
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006872 /* Check multi-process mode compatibility for the current proxy */
6873 if (global.nbproc > 1) {
6874 int nbproc = 0;
6875 if (curproxy->bind_proc) {
6876 int proc;
6877 for (proc = 0; proc < global.nbproc; proc++) {
6878 if (curproxy->bind_proc & (1 << proc)) {
6879 nbproc++;
6880 }
6881 }
6882 } else {
6883 nbproc = global.nbproc;
6884 }
6885 if (curproxy->table.peers.name) {
6886 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6887 curproxy->id);
6888 cfgerr++;
6889 }
6890 if (nbproc > 1) {
6891 if (curproxy->uri_auth) {
6892 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6893 curproxy->id);
6894 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6895 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6896 curproxy->id);
6897 }
6898 }
6899 if (curproxy->appsession_name) {
6900 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6901 curproxy->id);
6902 }
6903 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6904 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6905 curproxy->id);
6906 }
6907 }
6908 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006909
6910 /* create the task associated with the proxy */
6911 curproxy->task = task_new();
6912 if (curproxy->task) {
6913 curproxy->task->context = curproxy;
6914 curproxy->task->process = manage_proxy;
6915 /* no need to queue, it will be done automatically if some
6916 * listener gets limited.
6917 */
6918 curproxy->task->expire = TICK_ETERNITY;
6919 } else {
6920 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6921 curproxy->id);
6922 cfgerr++;
6923 }
6924
Willy Tarreaubaaee002006-06-26 02:48:02 +02006925 curproxy = curproxy->next;
6926 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006927
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006928 /* Check multi-process mode compatibility */
6929 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006930 if (global.stats_fe && !global.stats_fe->bind_proc) {
6931 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 +01006932 }
6933 }
6934
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006935 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6936 struct auth_users *curuser;
6937 int g;
6938
6939 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6940 unsigned int group_mask = 0;
6941 char *group = NULL;
6942
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006943 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006944 continue;
6945
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006946 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006947
6948 for (g = 0; g < curuserlist->grpcnt; g++)
6949 if (!strcmp(curuserlist->groups[g], group))
6950 break;
6951
6952 if (g == curuserlist->grpcnt) {
6953 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6954 curuserlist->name, group, curuser->user);
6955 err_code |= ERR_ALERT | ERR_FATAL;
6956 goto out;
6957 }
6958
6959 group_mask |= (1 << g);
6960 }
6961
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006962 free(curuser->u.groups);
6963 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006964 }
6965
6966 for (g = 0; g < curuserlist->grpcnt; g++) {
6967 char *user = NULL;
6968
6969 if (!curuserlist->groupusers[g])
6970 continue;
6971
6972 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6973 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6974 if (!strcmp(curuser->user, user))
6975 break;
6976
6977 if (!curuser) {
6978 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6979 curuserlist->name, user, curuserlist->groups[g]);
6980 err_code |= ERR_ALERT | ERR_FATAL;
6981 goto out;
6982 }
6983
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006984 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006985 }
6986
6987 free(curuserlist->groupusers[g]);
6988 }
6989
6990 free(curuserlist->groupusers);
6991
6992#ifdef DEBUG_AUTH
6993 for (g = 0; g < curuserlist->grpcnt; g++) {
6994 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6995
6996 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006997 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006998 fprintf(stderr, " %s", curuser->user);
6999 }
7000
7001 fprintf(stderr, "\n");
7002 }
7003#endif
7004
Willy Tarreaufbb78422011-06-05 15:38:35 +02007005 }
7006
7007 /* automatically compute fullconn if not set. We must not do it in the
7008 * loop above because cross-references are not yet fully resolved.
7009 */
7010 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7011 /* If <fullconn> is not set, let's set it to 10% of the sum of
7012 * the possible incoming frontend's maxconns.
7013 */
7014 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7015 struct proxy *fe;
7016 int total = 0;
7017
7018 /* sum up the number of maxconns of frontends which
7019 * reference this backend at least once or which are
7020 * the same one ('listen').
7021 */
7022 for (fe = proxy; fe; fe = fe->next) {
7023 struct switching_rule *rule;
7024 struct hdr_exp *exp;
7025 int found = 0;
7026
7027 if (!(fe->cap & PR_CAP_FE))
7028 continue;
7029
7030 if (fe == curproxy) /* we're on a "listen" instance */
7031 found = 1;
7032
7033 if (fe->defbe.be == curproxy) /* "default_backend" */
7034 found = 1;
7035
7036 /* check if a "use_backend" rule matches */
7037 if (!found) {
7038 list_for_each_entry(rule, &fe->switching_rules, list) {
7039 if (rule->be.backend == curproxy) {
7040 found = 1;
7041 break;
7042 }
7043 }
7044 }
7045
7046 /* check if a "reqsetbe" rule matches */
7047 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7048 if (exp->action == ACT_SETBE &&
7049 (struct proxy *)exp->replace == curproxy) {
7050 found = 1;
7051 break;
7052 }
7053 }
7054
7055 /* now we've checked all possible ways to reference a backend
7056 * from a frontend.
7057 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007058 if (!found)
7059 continue;
7060 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007061 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007062 /* we have the sum of the maxconns in <total>. We only
7063 * keep 10% of that sum to set the default fullconn, with
7064 * a hard minimum of 1 (to avoid a divide by zero).
7065 */
7066 curproxy->fullconn = (total + 9) / 10;
7067 if (!curproxy->fullconn)
7068 curproxy->fullconn = 1;
7069 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007070 }
7071
Willy Tarreau056f5682010-06-06 15:51:11 +02007072 /* initialize stick-tables on backend capable proxies. This must not
7073 * be done earlier because the data size may be discovered while parsing
7074 * other proxies.
7075 */
7076 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007077 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007078
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007079 /*
7080 * Recount currently required checks.
7081 */
7082
7083 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7084 int optnum;
7085
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007086 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7087 if (curproxy->options & cfg_opts[optnum].val)
7088 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007089
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007090 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7091 if (curproxy->options2 & cfg_opts2[optnum].val)
7092 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007093 }
7094
Willy Tarreau122541c2011-09-07 21:24:49 +02007095 if (peers) {
7096 struct peers *curpeers = peers, **last;
7097 struct peer *p, *pb;
7098
7099 /* Remove all peers sections which don't have a valid listener.
7100 * This can happen when a peers section is never referenced and
7101 * does not contain a local peer.
7102 */
7103 last = &peers;
7104 while (*last) {
7105 curpeers = *last;
7106 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007107 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007108 last = &curpeers->next;
7109 continue;
7110 }
7111
7112 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7113 curpeers->id, localpeer);
7114
7115 p = curpeers->remote;
7116 while (p) {
7117 pb = p->next;
7118 free(p->id);
7119 free(p);
7120 p = pb;
7121 }
7122
7123 /* Destroy and unlink this curpeers section.
7124 * Note: curpeers is backed up into *last.
7125 */
7126 free(curpeers->id);
7127 curpeers = curpeers->next;
7128 free(*last);
7129 *last = curpeers;
7130 }
7131 }
7132
Willy Tarreau34eb6712011-10-24 18:15:04 +02007133 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007134 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007135 MEM_F_SHARED);
7136
Willy Tarreaubb925012009-07-23 13:36:36 +02007137 if (cfgerr > 0)
7138 err_code |= ERR_ALERT | ERR_FATAL;
7139 out:
7140 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007141}
7142
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007143/*
7144 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7145 * parsing sessions.
7146 */
7147void cfg_register_keywords(struct cfg_kw_list *kwl)
7148{
7149 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7150}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007151
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007152/*
7153 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7154 */
7155void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7156{
7157 LIST_DEL(&kwl->list);
7158 LIST_INIT(&kwl->list);
7159}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160
7161/*
7162 * Local variables:
7163 * c-indent-level: 8
7164 * c-basic-offset: 8
7165 * End:
7166 */