blob: bbe9346a1912a3e4ab4a05498b95f02527b40ca7 [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) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
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
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 ss2 = str2sa_range(str, &port, &end, err,
218 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
219 if (!ss2)
220 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100222 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100223 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100228 if (!port || !end) {
229 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
230 goto fail;
231 }
232
Emeric Bruned760922010-10-22 17:59:25 +0200233 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200235 goto fail;
236 }
237
238 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200239 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200240 goto fail;
241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 }
243
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 /* OK the address looks correct */
245 ss = *ss2;
246
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247 for (; port <= end; port++) {
248 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100249 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200250 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
251 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
252 l->frontend = curproxy;
253 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200257 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100258 l->state = LI_INIT;
259
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 tcpv4_add_listener(l);
263 }
Emeric Bruned760922010-10-22 17:59:25 +0200264 else if (ss.ss_family == AF_INET6) {
265 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
266 tcpv6_add_listener(l);
267 }
268 else {
Emeric Bruned760922010-10-22 17:59:25 +0200269 uxst_add_listener(l);
270 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200272 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100273 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 } /* end for(port) */
275 } /* end while(next) */
276 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200277 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 fail:
279 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281}
282
Willy Tarreau977b8e42006-12-29 14:19:17 +0100283/*
284 * Sends a warning if proxy <proxy> does not have at least one of the
285 * capabilities in <cap>. An optionnal <hint> may be added at the end
286 * of the warning to help the user. Returns 1 if a warning was emitted
287 * or 0 if the condition is valid.
288 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100289int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100290{
291 char *msg;
292
293 switch (cap) {
294 case PR_CAP_BE: msg = "no backend"; break;
295 case PR_CAP_FE: msg = "no frontend"; break;
296 case PR_CAP_RS: msg = "no ruleset"; break;
297 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
298 default: msg = "not enough"; break;
299 }
300
301 if (!(proxy->cap & cap)) {
302 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100303 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100304 return 1;
305 }
306 return 0;
307}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308
Willy Tarreau61d18892009-03-31 10:49:21 +0200309/* Report a warning if a rule is placed after a 'block' rule.
310 * Return 1 if the warning has been emitted, otherwise 0.
311 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100312int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200313{
314 if (!LIST_ISEMPTY(&proxy->block_cond)) {
315 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
316 file, line, arg);
317 return 1;
318 }
319 return 0;
320}
321
322/* Report a warning if a rule is placed after a reqrewrite rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100325int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200326{
327 if (proxy->req_exp) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
335/* Report a warning if a rule is placed after a reqadd rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100340 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
348/* Report a warning if a rule is placed after a redirect rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100351int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200352{
353 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
354 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
361/* Report a warning if a rule is placed after a 'use_backend' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
378 warnif_rule_after_reqadd(proxy, file, line, arg) ||
379 warnif_rule_after_redirect(proxy, file, line, arg) ||
380 warnif_rule_after_use_backend(proxy, file, line, arg);
381}
382
383/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
387 warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
391/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 return warnif_rule_after_redirect(proxy, file, line, arg) ||
395 warnif_rule_after_use_backend(proxy, file, line, arg);
396}
397
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100398/* Report it if a request ACL condition uses some response-only parameters. It
399 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
400 * Note that <cond> may be NULL and then will be ignored.
401 */
402static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
403{
404 struct acl *acl;
405
406 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
407 return 0;
408
409 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
410 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
411 file, line, acl ? acl->name : "(unknown)");
412 return ERR_WARN;
413}
414
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100415/* Report it if a request ACL condition uses some request-only volatile parameters.
416 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
417 * Note that <cond> may be NULL and then will be ignored.
418 */
419static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
420{
421 struct acl *acl;
422
423 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
424 return 0;
425
426 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
427 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
428 file, line, acl ? acl->name : "(unknown)");
429 return ERR_WARN;
430}
431
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100432
Willy Tarreaubaaee002006-06-26 02:48:02 +0200433/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200434 * parse a line in a <global> section. Returns the error code, 0 if OK, or
435 * any combination of :
436 * - ERR_ABORT: must abort ASAP
437 * - ERR_FATAL: we can continue parsing but not start the service
438 * - ERR_WARN: a warning has been emitted
439 * - ERR_ALERT: an alert has been emitted
440 * Only the two first ones can stop processing, the two others are just
441 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200443int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444{
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200446 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200447
448 if (!strcmp(args[0], "global")) { /* new section */
449 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200452 else if (!strcmp(args[0], "ca-base")) {
453#ifdef USE_OPENSSL
454 if (global.ca_base != NULL) {
455 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
456 err_code |= ERR_ALERT;
457 goto out;
458 }
459 if (*(args[1]) == 0) {
460 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
461 err_code |= ERR_ALERT | ERR_FATAL;
462 goto out;
463 }
464 global.ca_base = strdup(args[1]);
465#else
466 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
467 err_code |= ERR_ALERT | ERR_FATAL;
468 goto out;
469#endif
470 }
471 else if (!strcmp(args[0], "crt-base")) {
472#ifdef USE_OPENSSL
473 if (global.crt_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.crt_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 else if (!strcmp(args[0], "daemon")) {
491 global.mode |= MODE_DAEMON;
492 }
493 else if (!strcmp(args[0], "debug")) {
494 global.mode |= MODE_DEBUG;
495 }
496 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100497 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100500 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100503 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100505 else if (!strcmp(args[0], "nosplice")) {
506 global.tune.options &= ~GTUNE_USE_SPLICE;
507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 else if (!strcmp(args[0], "quiet")) {
509 global.mode |= MODE_QUIET;
510 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200511 else if (!strcmp(args[0], "tune.maxpollevents")) {
512 if (global.tune.maxpollevents != 0) {
513 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200514 err_code |= ERR_ALERT;
515 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200516 }
517 if (*(args[1]) == 0) {
518 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200519 err_code |= ERR_ALERT | ERR_FATAL;
520 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200521 }
522 global.tune.maxpollevents = atol(args[1]);
523 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100524 else if (!strcmp(args[0], "tune.maxaccept")) {
525 if (global.tune.maxaccept != 0) {
526 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200527 err_code |= ERR_ALERT;
528 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100529 }
530 if (*(args[1]) == 0) {
531 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200532 err_code |= ERR_ALERT | ERR_FATAL;
533 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100534 }
535 global.tune.maxaccept = atol(args[1]);
536 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200537 else if (!strcmp(args[0], "tune.chksize")) {
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
542 }
543 global.tune.chksize = atol(args[1]);
544 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200545#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100546 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.sslcachesize = atol(args[1]);
553 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100554 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
555 unsigned int ssllifetime;
556 const char *res;
557
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563
564 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
565 if (res) {
566 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
567 file, linenum, *res, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571
572 global.tune.ssllifetime = ssllifetime;
573 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100574 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.tune.ssl_max_record = atol(args[1]);
581 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200582#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200583 else if (!strcmp(args[0], "tune.bufsize")) {
584 if (*(args[1]) == 0) {
585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589 global.tune.bufsize = atol(args[1]);
590 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
591 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100592 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200593 }
594 else if (!strcmp(args[0], "tune.maxrewrite")) {
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.maxrewrite = atol(args[1]);
601 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
602 global.tune.maxrewrite = global.tune.bufsize / 2;
603 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100604 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
605 if (global.tune.client_rcvbuf != 0) {
606 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT;
608 goto out;
609 }
610 if (*(args[1]) == 0) {
611 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT | ERR_FATAL;
613 goto out;
614 }
615 global.tune.client_rcvbuf = atol(args[1]);
616 }
617 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
618 if (global.tune.server_rcvbuf != 0) {
619 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT;
621 goto out;
622 }
623 if (*(args[1]) == 0) {
624 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT | ERR_FATAL;
626 goto out;
627 }
628 global.tune.server_rcvbuf = atol(args[1]);
629 }
630 else if (!strcmp(args[0], "tune.sndbuf.client")) {
631 if (global.tune.client_sndbuf != 0) {
632 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT;
634 goto out;
635 }
636 if (*(args[1]) == 0) {
637 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
640 }
641 global.tune.client_sndbuf = atol(args[1]);
642 }
643 else if (!strcmp(args[0], "tune.sndbuf.server")) {
644 if (global.tune.server_sndbuf != 0) {
645 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
646 err_code |= ERR_ALERT;
647 goto out;
648 }
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.server_sndbuf = atol(args[1]);
655 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200656 else if (!strcmp(args[0], "tune.pipesize")) {
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.pipesize = atol(args[1]);
663 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100664 else if (!strcmp(args[0], "tune.http.cookielen")) {
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.cookie_len = atol(args[1]) + 1;
671 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200672 else if (!strcmp(args[0], "tune.http.maxhdr")) {
673 if (*(args[1]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678 global.tune.max_http_hdr = atol(args[1]);
679 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100680 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
681#ifdef USE_ZLIB
682 if (*args[1]) {
683 global.tune.zlibmemlevel = atoi(args[1]);
684 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
685 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
686 file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 } else {
691 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
692 file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696#else
697 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
700#endif
701 }
702 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
703#ifdef USE_ZLIB
704 if (*args[1]) {
705 global.tune.zlibwindowsize = atoi(args[1]);
706 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
707 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
708 file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 } else {
713 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
714 file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718#else
719 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722#endif
723 }
William Lallemandf3747832012-11-09 12:33:10 +0100724 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
725 if (*args[1]) {
726 global.tune.comp_maxlevel = atoi(args[1]);
727 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
728 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
729 file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 } else {
734 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
735 file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 else if (!strcmp(args[0], "uid")) {
741 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200742 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT;
744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 }
751 global.uid = atol(args[1]);
752 }
753 else if (!strcmp(args[0], "gid")) {
754 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200755 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763 }
764 global.gid = atol(args[1]);
765 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200766 /* user/group name handling */
767 else if (!strcmp(args[0], "user")) {
768 struct passwd *ha_user;
769 if (global.uid != 0) {
770 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT;
772 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200773 }
774 errno = 0;
775 ha_user = getpwnam(args[1]);
776 if (ha_user != NULL) {
777 global.uid = (int)ha_user->pw_uid;
778 }
779 else {
780 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 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200782 }
783 }
784 else if (!strcmp(args[0], "group")) {
785 struct group *ha_group;
786 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200787 Alert("parsing [%s:%d] : gid/group was 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_group = getgrnam(args[1]);
793 if (ha_group != NULL) {
794 global.gid = (int)ha_group->gr_gid;
795 }
796 else {
797 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 +0200798 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200799 }
800 }
801 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 global.nbproc = atol(args[1]);
809 }
810 else if (!strcmp(args[0], "maxconn")) {
811 if (global.maxconn != 0) {
812 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 }
816 if (*(args[1]) == 0) {
817 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200818 err_code |= ERR_ALERT | ERR_FATAL;
819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 }
821 global.maxconn = atol(args[1]);
822#ifdef SYSTEM_MAXCONN
823 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
824 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);
825 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828#endif /* SYSTEM_MAXCONN */
829 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200830 else if (!strcmp(args[0], "maxsslconn")) {
831#ifdef USE_OPENSSL
832 if (*(args[1]) == 0) {
833 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 global.maxsslconn = atol(args[1]);
838#else
Emeric Brun0914df82012-10-02 18:45:42 +0200839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200842#endif
843 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200844 else if (!strcmp(args[0], "maxconnrate")) {
845 if (global.cps_lim != 0) {
846 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT;
848 goto out;
849 }
850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 global.cps_lim = atol(args[1]);
856 }
William Lallemandd85f9172012-11-09 17:05:39 +0100857 else if (!strcmp(args[0], "maxcomprate")) {
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 global.comp_rate_lim = atoi(args[1]) * 1024;
864 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100865 else if (!strcmp(args[0], "maxpipes")) {
866 if (global.maxpipes != 0) {
867 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
869 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100870 }
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100875 }
876 global.maxpipes = atol(args[1]);
877 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100878 else if (!strcmp(args[0], "maxzlibmem")) {
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
William Lallemande3a7d992012-11-20 11:25:20 +0100884 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100885 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100886 else if (!strcmp(args[0], "maxcompcpuusage")) {
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100893 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100894 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898}
899
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 else if (!strcmp(args[0], "ulimit-n")) {
901 if (global.rlimit_nofile != 0) {
902 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 global.rlimit_nofile = atol(args[1]);
912 }
913 else if (!strcmp(args[0], "chroot")) {
914 if (global.chroot != NULL) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
924 global.chroot = strdup(args[1]);
925 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200926 else if (!strcmp(args[0], "description")) {
927 int i, len=0;
928 char *d;
929
930 if (!*args[1]) {
931 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
932 file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936
937 for(i=1; *args[i]; i++)
938 len += strlen(args[i])+1;
939
940 if (global.desc)
941 free(global.desc);
942
943 global.desc = d = (char *)calloc(1, len);
944
945 d += sprintf(d, "%s", args[1]);
946 for(i=2; *args[i]; i++)
947 d += sprintf(d, " %s", args[i]);
948 }
949 else if (!strcmp(args[0], "node")) {
950 int i;
951 char c;
952
953 for (i=0; args[1][i]; i++) {
954 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100955 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
956 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200957 break;
958 }
959
960 if (!i || args[1][i]) {
961 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
962 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
963 file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967
968 if (global.node)
969 free(global.node);
970
971 global.node = strdup(args[1]);
972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 else if (!strcmp(args[0], "pidfile")) {
974 if (global.pidfile != NULL) {
975 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT;
977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 }
984 global.pidfile = strdup(args[1]);
985 }
Emeric Bruned760922010-10-22 17:59:25 +0200986 else if (!strcmp(args[0], "unix-bind")) {
987 int cur_arg = 1;
988 while (*(args[cur_arg])) {
989 if (!strcmp(args[cur_arg], "prefix")) {
990 if (global.unix_bind.prefix != NULL) {
991 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
992 err_code |= ERR_ALERT;
993 cur_arg += 2;
994 continue;
995 }
996
997 if (*(args[cur_arg+1]) == 0) {
998 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1003 cur_arg += 2;
1004 continue;
1005 }
1006
1007 if (!strcmp(args[cur_arg], "mode")) {
1008
1009 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1010 cur_arg += 2;
1011 continue;
1012 }
1013
1014 if (!strcmp(args[cur_arg], "uid")) {
1015
1016 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1017 cur_arg += 2;
1018 continue;
1019 }
1020
1021 if (!strcmp(args[cur_arg], "gid")) {
1022
1023 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1024 cur_arg += 2;
1025 continue;
1026 }
1027
1028 if (!strcmp(args[cur_arg], "user")) {
1029 struct passwd *user;
1030
1031 user = getpwnam(args[cur_arg + 1]);
1032 if (!user) {
1033 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1034 file, linenum, args[0], args[cur_arg + 1 ]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038
1039 global.unix_bind.ux.uid = user->pw_uid;
1040 cur_arg += 2;
1041 continue;
1042 }
1043
1044 if (!strcmp(args[cur_arg], "group")) {
1045 struct group *group;
1046
1047 group = getgrnam(args[cur_arg + 1]);
1048 if (!group) {
1049 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1050 file, linenum, args[0], args[cur_arg + 1 ]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
1054
1055 global.unix_bind.ux.gid = group->gr_gid;
1056 cur_arg += 2;
1057 continue;
1058 }
1059
Willy Tarreaub48f9582011-09-05 01:17:06 +02001060 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001061 file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 }
William Lallemand0f99e342011-10-12 17:50:54 +02001066 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1067 /* delete previous herited or defined syslog servers */
1068 struct logsrv *back;
1069 struct logsrv *tmp;
1070
1071 if (*(args[1]) != 0) {
1072 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076
1077 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1078 LIST_DEL(&tmp->list);
1079 free(tmp);
1080 }
1081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001083 struct sockaddr_storage *sk;
1084 int port1, port2;
1085 char *err_msg = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02001086 struct logsrv *logsrv;
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (*(args[1]) == 0 || *(args[2]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
William Lallemand0f99e342011-10-12 17:50:54 +02001093
1094 logsrv = calloc(1, sizeof(struct logsrv));
1095
1096 logsrv->facility = get_log_facility(args[2]);
1097 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001100 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
1102
William Lallemand0f99e342011-10-12 17:50:54 +02001103 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001105 logsrv->level = get_log_level(args[3]);
1106 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111 }
1112
William Lallemand0f99e342011-10-12 17:50:54 +02001113 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001114 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001115 logsrv->minlvl = get_log_level(args[4]);
1116 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001117 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001120 }
1121 }
1122
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001123 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
1124 if (!sk) {
1125 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], err_msg);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 free(err_msg);
1128 free(logsrv);
1129 goto out;
1130 }
1131 logsrv->addr = *sk;
1132 free(err_msg);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001133
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001134 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001135 if (port1 != port2) {
1136 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1137 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001138 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001139 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001140 goto out;
1141 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001142
William Lallemand0f99e342011-10-12 17:50:54 +02001143 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001144 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001145 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
William Lallemand0f99e342011-10-12 17:50:54 +02001148 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001149 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001150 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1151 char *name;
1152 int len;
1153
1154 if (global.log_send_hostname != NULL) {
1155 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1156 err_code |= ERR_ALERT;
1157 goto out;
1158 }
1159
1160 if (*(args[1]))
1161 name = args[1];
1162 else
1163 name = hostname;
1164
1165 len = strlen(name);
1166
1167 /* We'll add a space after the name to respect the log format */
1168 free(global.log_send_hostname);
1169 global.log_send_hostname = malloc(len + 2);
1170 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1171 }
Kevinm48936af2010-12-22 16:08:21 +00001172 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
1177 }
1178 free(global.log_tag);
1179 global.log_tag = strdup(args[1]);
1180 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001181 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1182 if (global.spread_checks != 0) {
1183 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001191 }
1192 global.spread_checks = atol(args[1]);
1193 if (global.spread_checks < 0 || global.spread_checks > 50) {
1194 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001198 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1199#ifdef USE_CPU_AFFINITY
1200 int cur_arg, i;
1201 unsigned int proc = 0;
1202 unsigned long cpus = 0;
1203
1204 if (strcmp(args[1], "all") == 0)
1205 proc = 0xFFFFFFFF;
1206 else if (strcmp(args[1], "odd") == 0)
1207 proc = 0x55555555;
1208 else if (strcmp(args[1], "even") == 0)
1209 proc = 0xAAAAAAAA;
1210 else {
1211 proc = atoi(args[1]);
1212 if (proc >= 1 && proc <= 32)
1213 proc = 1 << (proc - 1);
1214 }
1215
1216 if (!proc || !*args[2]) {
1217 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",
1218 file, linenum, args[0]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 cur_arg = 2;
1224 while (*args[cur_arg]) {
1225 unsigned int low, high;
1226
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001227 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001228 char *dash = strchr(args[cur_arg], '-');
1229
1230 low = high = str2uic(args[cur_arg]);
1231 if (dash)
1232 high = str2uic(dash + 1);
1233
1234 if (high < low) {
1235 unsigned int swap = low;
1236 low = high;
1237 high = swap;
1238 }
1239
1240 if (low < 0 || high >= sizeof(long) * 8) {
1241 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1242 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 while (low <= high)
1248 cpus |= 1UL << low++;
1249 }
1250 else {
1251 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1252 file, linenum, args[0], args[cur_arg]);
1253 err_code |= ERR_ALERT | ERR_FATAL;
1254 goto out;
1255 }
1256 cur_arg++;
1257 }
1258 for (i = 0; i < 32; i++)
1259 if (proc & (1 << i))
1260 global.cpu_map[i] = cpus;
1261#else
1262 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265#endif
1266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001268 struct cfg_kw_list *kwl;
1269 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001270 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001271
1272 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1273 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1274 if (kwl->kw[index].section != CFG_GLOBAL)
1275 continue;
1276 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001277 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001278 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001279 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001281 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001282 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001283 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001284 err_code |= ERR_WARN;
1285 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
1289 }
1290 }
1291
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001295
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001297 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001298 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299}
1300
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001301void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001303 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 defproxy.mode = PR_MODE_TCP;
1305 defproxy.state = PR_STNEW;
1306 defproxy.maxconn = cfg_maxpconn;
1307 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001308
1309 defproxy.defsrv.inter = DEF_CHKINTR;
1310 defproxy.defsrv.fastinter = 0;
1311 defproxy.defsrv.downinter = 0;
1312 defproxy.defsrv.rise = DEF_RISETIME;
1313 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001314 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315 defproxy.defsrv.maxqueue = 0;
1316 defproxy.defsrv.minconn = 0;
1317 defproxy.defsrv.maxconn = 0;
1318 defproxy.defsrv.slowstart = 0;
1319 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1320 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1321 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322}
1323
Willy Tarreauade5ec42010-01-28 19:33:49 +01001324
1325static int create_cond_regex_rule(const char *file, int line,
1326 struct proxy *px, int dir, int action, int flags,
1327 const char *cmd, const char *reg, const char *repl,
1328 const char **cond_start)
1329{
1330 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001331 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001332 const char *err;
1333 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001334 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001335
1336 if (px == &defproxy) {
1337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto err;
1340 }
1341
1342 if (*reg == 0) {
1343 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto err;
1346 }
1347
1348 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1349 err_code |= ERR_WARN;
1350
Willy Tarreau5321c422010-01-28 20:35:13 +01001351 if (cond_start &&
1352 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001353 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1354 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1355 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto err;
1358 }
1359 }
1360 else if (cond_start && **cond_start) {
1361 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1362 file, line, cmd, *cond_start);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001367 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001368 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001369 else
1370 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001371
Willy Tarreauade5ec42010-01-28 19:33:49 +01001372 preg = calloc(1, sizeof(regex_t));
1373 if (!preg) {
1374 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1375 err_code = ERR_ALERT | ERR_FATAL;
1376 goto err;
1377 }
1378
1379 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1380 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1381 err_code = ERR_ALERT | ERR_FATAL;
1382 goto err;
1383 }
1384
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001385 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001386 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001387 if (repl && err) {
1388 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1389 file, line, cmd, *err);
1390 err_code |= ERR_ALERT | ERR_FATAL;
1391 goto err;
1392 }
1393
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001394 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 err_code |= ERR_WARN;
1396
Willy Tarreauf4068b62012-05-08 17:37:49 +02001397 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001398 return err_code;
1399 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001400 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001401 free(preg);
1402 return err_code;
1403}
1404
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001407 * Returns the error code, 0 if OK, or any combination of :
1408 * - ERR_ABORT: must abort ASAP
1409 * - ERR_FATAL: we can continue parsing but not start the service
1410 * - ERR_WARN: a warning has been emitted
1411 * - ERR_ALERT: an alert has been emitted
1412 * Only the two first ones can stop processing, the two others are just
1413 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001415int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1416{
1417 static struct peers *curpeers = NULL;
1418 struct peer *newpeer = NULL;
1419 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001420 struct bind_conf *bind_conf;
1421 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001422 int err_code = 0;
1423
1424 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001425 if (!*args[1]) {
1426 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
1429 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001430
1431 err = invalid_char(args[1]);
1432 if (err) {
1433 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1434 file, linenum, *err, args[0], args[1]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001436 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001437 }
1438
1439 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1440 /*
1441 * If there are two proxies with the same name only following
1442 * combinations are allowed:
1443 */
1444 if (strcmp(curpeers->id, args[1]) == 0) {
1445 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1446 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1447 err_code |= ERR_WARN;
1448 }
1449 }
1450
1451 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1453 err_code |= ERR_ALERT | ERR_ABORT;
1454 goto out;
1455 }
1456
1457 curpeers->next = peers;
1458 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001459 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001460 curpeers->conf.line = linenum;
1461 curpeers->last_change = now.tv_sec;
1462 curpeers->id = strdup(args[1]);
1463 }
1464 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001465 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001466 int port1, port2;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001467 char *err_msg = NULL;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001468 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001469
1470 if (!*args[2]) {
1471 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1472 file, linenum, args[0]);
1473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto out;
1475 }
1476
1477 err = invalid_char(args[1]);
1478 if (err) {
1479 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1480 file, linenum, *err, args[1]);
1481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1486 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1487 err_code |= ERR_ALERT | ERR_ABORT;
1488 goto out;
1489 }
1490
1491 /* the peers are linked backwards first */
1492 curpeers->count++;
1493 newpeer->next = curpeers->remote;
1494 curpeers->remote = newpeer;
1495 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001496 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001497 newpeer->conf.line = linenum;
1498
1499 newpeer->last_change = now.tv_sec;
1500 newpeer->id = strdup(args[1]);
1501
Willy Tarreaub36487e2013-03-10 18:37:42 +01001502 sk = str2sa_range(args[2], &port1, &port2, &err_msg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001503 if (!sk) {
Willy Tarreaub36487e2013-03-10 18:37:42 +01001504 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001505 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001506 free(err_msg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001507 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001508 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001509 free(err_msg);
1510
1511 proto = protocol_by_family(sk->ss_family);
1512 if (!proto || !proto->connect) {
1513 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1514 file, linenum, args[0], args[1]);
1515 err_code |= ERR_ALERT | ERR_FATAL;
1516 goto out;
1517 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001518
1519 if (port1 != port2) {
1520 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1521 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001522 err_code |= ERR_ALERT | ERR_FATAL;
1523 goto out;
1524 }
1525
Willy Tarreau2aa38802013-02-20 19:20:59 +01001526 if (!port1) {
1527 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port 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 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001532
Emeric Brun32da3c42010-09-23 18:39:19 +02001533 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001534 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001535 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001536 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001537
Emeric Brun32da3c42010-09-23 18:39:19 +02001538 if (strcmp(newpeer->id, localpeer) == 0) {
1539 /* Current is local peer, it define a frontend */
1540 newpeer->local = 1;
1541
1542 if (!curpeers->peers_fe) {
1543 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1544 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1545 err_code |= ERR_ALERT | ERR_ABORT;
1546 goto out;
1547 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001548
Willy Tarreau237250c2011-07-29 01:49:03 +02001549 init_new_proxy(curpeers->peers_fe);
1550 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001551
1552 curpeers->peers_fe->last_change = now.tv_sec;
1553 curpeers->peers_fe->id = strdup(args[1]);
1554 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001555 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1557 curpeers->peers_fe->timeout.connect = 5000;
1558 curpeers->peers_fe->accept = peer_accept;
1559 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001560 curpeers->peers_fe->conf.file = strdup(file);
1561 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001562
1563 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1564
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001565 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1566 if (err_msg && *err_msg) {
1567 indent_msg(&err_msg, 2);
1568 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1569 }
1570 else
1571 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1572 file, linenum, args[0], args[1], args[2]);
1573 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001574 err_code |= ERR_FATAL;
1575 goto out;
1576 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001577
1578 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1579 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1580 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1581 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1582 l->accept = session_accept;
1583 l->handler = process_session;
1584 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1585 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1586 global.maxsock += l->maxconn;
1587 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001588 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001589 else {
1590 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1591 file, linenum, args[0], args[1],
1592 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1593 err_code |= ERR_FATAL;
1594 goto out;
1595 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001596 }
1597 } /* neither "peer" nor "peers" */
1598 else if (*args[0] != 0) {
1599 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1600 err_code |= ERR_ALERT | ERR_FATAL;
1601 goto out;
1602 }
1603
1604out:
1605 return err_code;
1606}
1607
1608
Willy Tarreau3842f002009-06-14 11:39:52 +02001609int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610{
1611 static struct proxy *curproxy = NULL;
1612 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001613 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001614 int rc;
1615 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001616 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001617 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001618 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001619 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001620 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621
Willy Tarreau977b8e42006-12-29 14:19:17 +01001622 if (!strcmp(args[0], "listen"))
1623 rc = PR_CAP_LISTEN;
1624 else if (!strcmp(args[0], "frontend"))
1625 rc = PR_CAP_FE | PR_CAP_RS;
1626 else if (!strcmp(args[0], "backend"))
1627 rc = PR_CAP_BE | PR_CAP_RS;
1628 else if (!strcmp(args[0], "ruleset"))
1629 rc = PR_CAP_RS;
1630 else
1631 rc = PR_CAP_NONE;
1632
1633 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 if (!*args[1]) {
1635 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1636 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_ABORT;
1639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001640 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001641
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001642 err = invalid_char(args[1]);
1643 if (err) {
1644 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1645 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001646 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001647 }
1648
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001649 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1650 /*
1651 * If there are two proxies with the same name only following
1652 * combinations are allowed:
1653 *
1654 * listen backend frontend ruleset
1655 * listen - - - -
1656 * backend - - OK -
1657 * frontend - OK - -
1658 * ruleset - - - -
1659 */
1660
1661 if (!strcmp(curproxy->id, args[1]) &&
1662 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1663 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001664 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1665 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1666 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001668 }
1669 }
1670
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1672 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001673 err_code |= ERR_ALERT | ERR_ABORT;
1674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001676
Willy Tarreau97cb7802010-01-03 20:23:58 +01001677 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 curproxy->next = proxy;
1679 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001680 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001681 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001682 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001684 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685
1686 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001687 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001688 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001689 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001690
Willy Tarreau4348fad2012-09-20 16:48:07 +02001691 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1692
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001693 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1694 if (err_msg && *err_msg) {
1695 indent_msg(&err_msg, 2);
1696 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1697 }
1698 else
1699 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1700 file, linenum, args[0], args[1], args[2]);
1701 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001702 err_code |= ERR_FATAL;
1703 goto out;
1704 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001705
Willy Tarreau4348fad2012-09-20 16:48:07 +02001706 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001707 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 }
1710
1711 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001712 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001713 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001714
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001717 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001718 curproxy->no_options = defproxy.no_options;
1719 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001720 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001721 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001722 curproxy->except_net = defproxy.except_net;
1723 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001724 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001725 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001727 if (defproxy.fwdfor_hdr_len) {
1728 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1729 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1730 }
1731
Willy Tarreaub86db342009-11-30 11:50:16 +01001732 if (defproxy.orgto_hdr_len) {
1733 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1734 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1735 }
1736
Mark Lamourinec2247f02012-01-04 13:02:01 -05001737 if (defproxy.server_id_hdr_len) {
1738 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1739 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1740 }
1741
Willy Tarreau977b8e42006-12-29 14:19:17 +01001742 if (curproxy->cap & PR_CAP_FE) {
1743 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001744 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001745 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001746
1747 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001748 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1749 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001750
1751 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753
Willy Tarreau977b8e42006-12-29 14:19:17 +01001754 if (curproxy->cap & PR_CAP_BE) {
1755 curproxy->fullconn = defproxy.fullconn;
1756 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001758 if (defproxy.check_req) {
1759 curproxy->check_req = calloc(1, defproxy.check_len);
1760 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1761 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001762 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001764 if (defproxy.expect_str) {
1765 curproxy->expect_str = strdup(defproxy.expect_str);
1766 if (defproxy.expect_regex) {
1767 /* note: this regex is known to be valid */
1768 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1769 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1770 }
1771 }
1772
Willy Tarreau67402132012-05-31 20:40:20 +02001773 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001774 if (defproxy.cookie_name)
1775 curproxy->cookie_name = strdup(defproxy.cookie_name);
1776 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001777 if (defproxy.cookie_domain)
1778 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001779
Willy Tarreau31936852010-10-06 16:59:56 +02001780 if (defproxy.cookie_maxidle)
1781 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1782
1783 if (defproxy.cookie_maxlife)
1784 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1785
Emeric Brun647caf12009-06-30 17:57:00 +02001786 if (defproxy.rdp_cookie_name)
1787 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1788 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1789
Willy Tarreau01732802007-11-01 22:48:15 +01001790 if (defproxy.url_param_name)
1791 curproxy->url_param_name = strdup(defproxy.url_param_name);
1792 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001793
Benoitaffb4812009-03-25 13:02:10 +01001794 if (defproxy.hh_name)
1795 curproxy->hh_name = strdup(defproxy.hh_name);
1796 curproxy->hh_len = defproxy.hh_len;
1797 curproxy->hh_match_domain = defproxy.hh_match_domain;
1798
Willy Tarreauef9a3602012-12-08 22:29:20 +01001799 if (defproxy.conn_src.iface_name)
1800 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1801 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1802 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001805 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001806 if (defproxy.capture_name)
1807 curproxy->capture_name = strdup(defproxy.capture_name);
1808 curproxy->capture_namelen = defproxy.capture_namelen;
1809 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811
Willy Tarreau977b8e42006-12-29 14:19:17 +01001812 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001813 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001814 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001815 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001816 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001817 curproxy->uri_auth = defproxy.uri_auth;
1818 curproxy->mon_net = defproxy.mon_net;
1819 curproxy->mon_mask = defproxy.mon_mask;
1820 if (defproxy.monitor_uri)
1821 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1822 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001823 if (defproxy.defbe.name)
1824 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001825
1826 /* get either a pointer to the logformat string or a copy of it */
1827 curproxy->logformat_string = defproxy.logformat_string;
1828 if (curproxy->logformat_string &&
1829 curproxy->logformat_string != default_http_log_format &&
1830 curproxy->logformat_string != default_tcp_log_format &&
1831 curproxy->logformat_string != clf_http_log_format)
1832 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 }
1834
1835 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001836 curproxy->timeout.connect = defproxy.timeout.connect;
1837 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001838 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001839 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001840 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001841 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001842 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001843 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001844 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845 }
1846
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001848
1849 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001850 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001851 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001852 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001853 LIST_INIT(&node->list);
1854 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1855 }
1856
Willy Tarreau196729e2012-05-31 19:30:26 +02001857 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1858 if (curproxy->uniqueid_format_string)
1859 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001860
1861 /* copy default header unique id */
1862 if (defproxy.header_unique_id)
1863 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1864
William Lallemand82fe75c2012-10-23 10:25:10 +02001865 /* default compression options */
1866 if (defproxy.comp != NULL) {
1867 curproxy->comp = calloc(1, sizeof(struct comp));
1868 curproxy->comp->algos = defproxy.comp->algos;
1869 curproxy->comp->types = defproxy.comp->types;
1870 }
1871
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001873 curproxy->conf.used_listener_id = EB_ROOT;
1874 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001875
Willy Tarreau93893792009-07-23 13:19:11 +02001876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 }
1878 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1879 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001880 /* FIXME-20070101: we should do this too at the end of the
1881 * config parsing to free all default values.
1882 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001883 free(defproxy.check_req);
1884 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001885 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001886 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001887 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001888 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001889 free(defproxy.capture_name);
1890 free(defproxy.monitor_uri);
1891 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001892 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001893 free(defproxy.fwdfor_hdr_name);
1894 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001895 free(defproxy.orgto_hdr_name);
1896 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001897 free(defproxy.server_id_hdr_name);
1898 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001899 free(defproxy.expect_str);
1900 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001901
Willy Tarreau39b06652012-06-01 10:58:06 +02001902 if (defproxy.logformat_string != default_http_log_format &&
1903 defproxy.logformat_string != default_tcp_log_format &&
1904 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001905 free(defproxy.logformat_string);
1906
1907 free(defproxy.uniqueid_format_string);
1908
Willy Tarreaua534fea2008-08-03 12:19:50 +02001909 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001910 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001911
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 /* we cannot free uri_auth because it might already be used */
1913 init_default_instance();
1914 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001915 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 }
1918 else if (curproxy == NULL) {
1919 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
1923
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924
1925 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001927 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001928 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001929 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001930
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 if (curproxy == &defproxy) {
1932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001936 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938
Emeric Bruned760922010-10-22 17:59:25 +02001939 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001940 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001945
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001946 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001947
1948 /* use default settings for unix sockets */
1949 bind_conf->ux.uid = global.unix_bind.ux.uid;
1950 bind_conf->ux.gid = global.unix_bind.ux.gid;
1951 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001952
1953 /* NOTE: the following line might create several listeners if there
1954 * are comma-separated IPs or port ranges. So all further processing
1955 * will have to be applied to all listeners created after last_listen.
1956 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001957 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1958 if (err_msg && *err_msg) {
1959 indent_msg(&err_msg, 2);
1960 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1961 }
1962 else
1963 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1964 file, linenum, args[0], args[1]);
1965 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
1968 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001969
Willy Tarreau4348fad2012-09-20 16:48:07 +02001970 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1971 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001972 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001973 }
1974
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001975 cur_arg = 2;
1976 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001977 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001978 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001979 char *err;
1980
Willy Tarreau26982662012-09-12 23:17:10 +02001981 kw = bind_find_kw(args[cur_arg]);
1982 if (kw) {
1983 char *err = NULL;
1984 int code;
1985
1986 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001987 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1988 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001989 cur_arg += 1 + kw->skip ;
1990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
1992 }
1993
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001995 err_code |= code;
1996
1997 if (code) {
1998 if (err && *err) {
1999 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002000 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002001 }
2002 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002003 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2004 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002005 if (code & ERR_FATAL) {
2006 free(err);
2007 cur_arg += 1 + kw->skip;
2008 goto out;
2009 }
2010 }
2011 free(err);
2012 cur_arg += 1 + kw->skip;
2013 continue;
2014 }
2015
Willy Tarreau8638f482012-09-18 18:01:17 +02002016 err = NULL;
2017 if (!bind_dumped) {
2018 bind_dump_kws(&err);
2019 indent_msg(&err, 4);
2020 bind_dumped = 1;
2021 }
2022
2023 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2024 file, linenum, args[0], args[1], args[cur_arg],
2025 err ? " Registered keywords :" : "", err ? err : "");
2026 free(err);
2027
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002030 }
Willy Tarreau93893792009-07-23 13:19:11 +02002031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 }
2033 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2034 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2035 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 /* flush useless bits */
2044 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002050
Willy Tarreau1c47f852006-07-09 08:22:27 +02002051 if (!*args[1]) {
2052 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2053 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
2055 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002056 }
2057
Willy Tarreaua534fea2008-08-03 12:19:50 +02002058 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002059 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002060 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002061 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002062 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2063
Willy Tarreau93893792009-07-23 13:19:11 +02002064 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002065 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2067 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2068 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2069 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2070 else {
2071 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
2075 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002076 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002077 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002078
2079 if (curproxy == &defproxy) {
2080 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002084 }
2085
2086 if (!*args[1]) {
2087 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2088 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002091 }
2092
2093 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002094 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002095
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002096 if (curproxy->uuid <= 0) {
2097 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002098 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002101 }
2102
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002103 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2104 if (node) {
2105 struct proxy *target = container_of(node, struct proxy, conf.id);
2106 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2107 file, linenum, proxy_type_str(curproxy), curproxy->id,
2108 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
2111 }
2112 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002113 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002114 else if (!strcmp(args[0], "description")) {
2115 int i, len=0;
2116 char *d;
2117
Cyril Bonté99ed3272010-01-24 23:29:44 +01002118 if (curproxy == &defproxy) {
2119 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2120 file, linenum, args[0]);
2121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
2123 }
2124
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002125 if (!*args[1]) {
2126 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2127 file, linenum, args[0]);
2128 return -1;
2129 }
2130
2131 for(i=1; *args[i]; i++)
2132 len += strlen(args[i])+1;
2133
2134 d = (char *)calloc(1, len);
2135 curproxy->desc = d;
2136
2137 d += sprintf(d, "%s", args[1]);
2138 for(i=2; *args[i]; i++)
2139 d += sprintf(d, " %s", args[i]);
2140
2141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2143 curproxy->state = PR_STSTOPPED;
2144 }
2145 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2146 curproxy->state = PR_STNEW;
2147 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002148 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2149 int cur_arg = 1;
2150 unsigned int set = 0;
2151
2152 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002153 unsigned int low, high;
2154
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002155 if (strcmp(args[cur_arg], "all") == 0) {
2156 set = 0;
2157 break;
2158 }
2159 else if (strcmp(args[cur_arg], "odd") == 0) {
2160 set |= 0x55555555;
2161 }
2162 else if (strcmp(args[cur_arg], "even") == 0) {
2163 set |= 0xAAAAAAAA;
2164 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002165 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002166 char *dash = strchr(args[cur_arg], '-');
2167
2168 low = high = str2uic(args[cur_arg]);
2169 if (dash)
2170 high = str2uic(dash + 1);
2171
2172 if (high < low) {
2173 unsigned int swap = low;
2174 low = high;
2175 high = swap;
2176 }
2177
2178 if (low < 1 || high > 32) {
2179 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002183 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002184
2185 if (high > global.nbproc) {
2186 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2187 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002189 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002190 while (low <= high)
2191 set |= 1 << (low++ - 1);
2192 }
2193 else {
2194 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2195 file, linenum, args[0]);
2196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002198 }
2199 cur_arg++;
2200 }
2201 curproxy->bind_proc = set;
2202 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002203 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002204 if (curproxy == &defproxy) {
2205 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002208 }
2209
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002210 err = invalid_char(args[1]);
2211 if (err) {
2212 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2213 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002215 }
2216
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002217 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2218 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2219 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002222 }
2223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2225 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002229
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 if (*(args[1]) == 0) {
2231 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2232 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002236
Willy Tarreau67402132012-05-31 20:40:20 +02002237 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002238 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002239 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002240 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 curproxy->cookie_name = strdup(args[1]);
2242 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002243
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 cur_arg = 2;
2245 while (*(args[cur_arg])) {
2246 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
2252 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002253 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 }
2255 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002256 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
2258 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002259 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002261 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002262 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002265 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002267 else if (!strcmp(args[cur_arg], "httponly")) {
2268 curproxy->ck_opts |= PR_CK_HTTPONLY;
2269 }
2270 else if (!strcmp(args[cur_arg], "secure")) {
2271 curproxy->ck_opts |= PR_CK_SECURE;
2272 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 else if (!strcmp(args[cur_arg], "domain")) {
2274 if (!*args[cur_arg + 1]) {
2275 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2276 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002279 }
2280
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002281 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002282 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002283 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2284 " dots nor does not start with a dot."
2285 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002286 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002287 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002288 }
2289
2290 err = invalid_domainchar(args[cur_arg + 1]);
2291 if (err) {
2292 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2293 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002296 }
2297
Willy Tarreau68a897b2009-12-03 23:28:34 +01002298 if (!curproxy->cookie_domain) {
2299 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2300 } else {
2301 /* one domain was already specified, add another one by
2302 * building the string which will be returned along with
2303 * the cookie.
2304 */
2305 char *new_ptr;
2306 int new_len = strlen(curproxy->cookie_domain) +
2307 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2308 new_ptr = malloc(new_len);
2309 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2310 free(curproxy->cookie_domain);
2311 curproxy->cookie_domain = new_ptr;
2312 }
Willy Tarreau31936852010-10-06 16:59:56 +02002313 cur_arg++;
2314 }
2315 else if (!strcmp(args[cur_arg], "maxidle")) {
2316 unsigned int maxidle;
2317 const char *res;
2318
2319 if (!*args[cur_arg + 1]) {
2320 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2321 file, linenum, args[cur_arg]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325
2326 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2327 if (res) {
2328 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2329 file, linenum, *res, args[cur_arg]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 curproxy->cookie_maxidle = maxidle;
2334 cur_arg++;
2335 }
2336 else if (!strcmp(args[cur_arg], "maxlife")) {
2337 unsigned int maxlife;
2338 const char *res;
2339
2340 if (!*args[cur_arg + 1]) {
2341 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2342 file, linenum, args[cur_arg]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346
2347 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2348 if (res) {
2349 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2350 file, linenum, *res, args[cur_arg]);
2351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
2353 }
2354 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002355 cur_arg++;
2356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002358 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 +02002359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363 cur_arg++;
2364 }
Willy Tarreau67402132012-05-31 20:40:20 +02002365 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2367 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
2370
Willy Tarreau67402132012-05-31 20:40:20 +02002371 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2373 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002376
Willy Tarreau67402132012-05-31 20:40:20 +02002377 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002378 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2379 file, linenum);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002383 else if (!strcmp(args[0], "persist")) { /* persist */
2384 if (*(args[1]) == 0) {
2385 Alert("parsing [%s:%d] : missing persist method.\n",
2386 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002389 }
2390
2391 if (!strncmp(args[1], "rdp-cookie", 10)) {
2392 curproxy->options2 |= PR_O2_RDPC_PRST;
2393
Emeric Brunb982a3d2010-01-04 15:45:53 +01002394 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002395 const char *beg, *end;
2396
2397 beg = args[1] + 11;
2398 end = strchr(beg, ')');
2399
2400 if (!end || end == beg) {
2401 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2402 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002405 }
2406
2407 free(curproxy->rdp_cookie_name);
2408 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2409 curproxy->rdp_cookie_len = end-beg;
2410 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002411 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002412 free(curproxy->rdp_cookie_name);
2413 curproxy->rdp_cookie_name = strdup("msts");
2414 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2415 }
2416 else { /* syntax */
2417 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2418 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002421 }
2422 }
2423 else {
2424 Alert("parsing [%s:%d] : unknown persist method.\n",
2425 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002428 }
2429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002431 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002433 if (curproxy == &defproxy) {
2434 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002441
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002443 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 }
2448 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002449 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 curproxy->appsession_name = strdup(args[1]);
2451 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2452 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002453 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2454 if (err) {
2455 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2456 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002459 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002460 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002461
Willy Tarreau51041c72007-09-09 21:56:53 +02002462 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2463 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_ABORT;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002467
2468 cur_arg = 6;
2469 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002470 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2471 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002472 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002473 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002474 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002475 } else if (!strcmp(args[cur_arg], "prefix")) {
2476 curproxy->options2 |= PR_O2_AS_PFX;
2477 } else if (!strcmp(args[cur_arg], "mode")) {
2478 if (!*args[cur_arg + 1]) {
2479 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2480 file, linenum, args[0], args[cur_arg]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484
2485 cur_arg++;
2486 if (!strcmp(args[cur_arg], "query-string")) {
2487 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2488 curproxy->options2 |= PR_O2_AS_M_QS;
2489 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2490 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2491 curproxy->options2 |= PR_O2_AS_M_PP;
2492 } else {
2493 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498 cur_arg++;
2499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 } /* Url App Session */
2501 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002502 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002503 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002504
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002506 if (curproxy == &defproxy) {
2507 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
2510 }
2511
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 if (*(args[4]) == 0) {
2513 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2514 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002518 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 curproxy->capture_name = strdup(args[2]);
2520 curproxy->capture_namelen = strlen(curproxy->capture_name);
2521 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 curproxy->to_log |= LW_COOKIE;
2523 }
2524 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2525 struct cap_hdr *hdr;
2526
2527 if (curproxy == &defproxy) {
2528 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 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 }
2532
2533 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2534 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2535 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 }
2539
2540 hdr = calloc(sizeof(struct cap_hdr), 1);
2541 hdr->next = curproxy->req_cap;
2542 hdr->name = strdup(args[3]);
2543 hdr->namelen = strlen(args[3]);
2544 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002545 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 hdr->index = curproxy->nb_req_cap++;
2547 curproxy->req_cap = hdr;
2548 curproxy->to_log |= LW_REQHDR;
2549 }
2550 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2551 struct cap_hdr *hdr;
2552
2553 if (curproxy == &defproxy) {
2554 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 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 }
2558
2559 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2560 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2561 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 hdr = calloc(sizeof(struct cap_hdr), 1);
2566 hdr->next = curproxy->rsp_cap;
2567 hdr->name = strdup(args[3]);
2568 hdr->namelen = strlen(args[3]);
2569 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002570 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 hdr->index = curproxy->nb_rsp_cap++;
2572 curproxy->rsp_cap = hdr;
2573 curproxy->to_log |= LW_RSPHDR;
2574 }
2575 else {
2576 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002585
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 if (*(args[1]) == 0) {
2587 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 }
2592 curproxy->conn_retries = atol(args[1]);
2593 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002594 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002595 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002596
2597 if (curproxy == &defproxy) {
2598 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602
Willy Tarreau20b0de52012-12-24 15:45:22 +01002603 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2604 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2605 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2606 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2607 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2608 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 +01002609 file, linenum, args[0]);
2610 err_code |= ERR_WARN;
2611 }
2612
Willy Tarreauff011f22011-01-06 17:51:27 +01002613 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002614
Willy Tarreauff011f22011-01-06 17:51:27 +01002615 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002616 err_code |= ERR_ALERT | ERR_ABORT;
2617 goto out;
2618 }
2619
Willy Tarreauff011f22011-01-06 17:51:27 +01002620 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2621 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002622 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002623 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2624 /* set the header name and length into the proxy structure */
2625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2626 err_code |= ERR_WARN;
2627
2628 if (!*args[1]) {
2629 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2630 file, linenum, args[0]);
2631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
2633 }
2634
2635 /* set the desired header name */
2636 free(curproxy->server_id_hdr_name);
2637 curproxy->server_id_hdr_name = strdup(args[1]);
2638 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2639 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002640 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002641 if (curproxy == &defproxy) {
2642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002645 }
2646
Willy Tarreauef6494c2010-01-28 17:12:36 +01002647 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002648 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2649 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002652 }
2653
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002654 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2655 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2656 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002659 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002660
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002661 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002662 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002663 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002665 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002666
Cyril Bonté99ed3272010-01-24 23:29:44 +01002667 if (curproxy == &defproxy) {
2668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
2671 }
2672
Willy Tarreau4baae242012-12-27 12:00:31 +01002673 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2674 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2675 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 }
2679
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002681 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2682 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002683 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002684 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002685 struct switching_rule *rule;
2686
Willy Tarreaub099aca2008-10-12 17:26:37 +02002687 if (curproxy == &defproxy) {
2688 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002691 }
2692
Willy Tarreau55ea7572007-06-17 19:56:27 +02002693 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002695
2696 if (*(args[1]) == 0) {
2697 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002700 }
2701
Willy Tarreauef6494c2010-01-28 17:12:36 +01002702 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2704 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707 }
2708
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002709 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2710 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2711 file, linenum, errmsg);
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 Tarreauf1e98b82010-01-28 17:59:39 +01002716 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002717
Willy Tarreau55ea7572007-06-17 19:56:27 +02002718 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2719 rule->cond = cond;
2720 rule->be.name = strdup(args[1]);
2721 LIST_INIT(&rule->list);
2722 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2723 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002724 else if (strcmp(args[0], "use-server") == 0) {
2725 struct server_rule *rule;
2726
2727 if (curproxy == &defproxy) {
2728 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
2732
2733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2734 err_code |= ERR_WARN;
2735
2736 if (*(args[1]) == 0) {
2737 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741
2742 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2743 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2744 file, linenum, args[0]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002749 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2750 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2751 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2757
2758 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2759 rule->cond = cond;
2760 rule->srv.name = strdup(args[1]);
2761 LIST_INIT(&rule->list);
2762 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2763 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2764 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002765 else if ((!strcmp(args[0], "force-persist")) ||
2766 (!strcmp(args[0], "ignore-persist"))) {
2767 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002768
2769 if (curproxy == &defproxy) {
2770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774
2775 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2776 err_code |= ERR_WARN;
2777
Willy Tarreauef6494c2010-01-28 17:12:36 +01002778 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002779 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2780 file, linenum, args[0]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002785 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2786 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2787 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790 }
2791
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002792 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002793
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002794 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002795 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002796 if (!strcmp(args[0], "force-persist")) {
2797 rule->type = PERSIST_TYPE_FORCE;
2798 } else {
2799 rule->type = PERSIST_TYPE_IGNORE;
2800 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002801 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002802 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002803 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002804 else if (!strcmp(args[0], "stick-table")) {
2805 int myidx = 1;
2806
Emeric Brun32da3c42010-09-23 18:39:19 +02002807 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002808 curproxy->table.type = (unsigned int)-1;
2809 while (*args[myidx]) {
2810 const char *err;
2811
2812 if (strcmp(args[myidx], "size") == 0) {
2813 myidx++;
2814 if (!*(args[myidx])) {
2815 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2816 file, linenum, args[myidx-1]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2821 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2822 file, linenum, *err, args[myidx-1]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002826 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002827 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002828 else if (strcmp(args[myidx], "peers") == 0) {
2829 myidx++;
2830 if (!*(args[myidx])) {
2831 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2832 file, linenum, args[myidx-1]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836 curproxy->table.peers.name = strdup(args[myidx++]);
2837 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002838 else if (strcmp(args[myidx], "expire") == 0) {
2839 myidx++;
2840 if (!*(args[myidx])) {
2841 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2842 file, linenum, args[myidx-1]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
2846 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2847 if (err) {
2848 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2849 file, linenum, *err, args[myidx-1]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002854 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002855 }
2856 else if (strcmp(args[myidx], "nopurge") == 0) {
2857 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002858 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002859 }
2860 else if (strcmp(args[myidx], "type") == 0) {
2861 myidx++;
2862 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2863 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2864 file, linenum, args[myidx]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002868 /* myidx already points to next arg */
2869 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002870 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002871 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002872 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002873
2874 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002875 nw = args[myidx];
2876 while (*nw) {
2877 /* the "store" keyword supports a comma-separated list */
2878 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002879 sa = NULL; /* store arg */
2880 while (*nw && *nw != ',') {
2881 if (*nw == '(') {
2882 *nw = 0;
2883 sa = ++nw;
2884 while (*nw != ')') {
2885 if (!*nw) {
2886 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2887 file, linenum, args[0], cw);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891 nw++;
2892 }
2893 *nw = '\0';
2894 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002895 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002896 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002897 if (*nw)
2898 *nw++ = '\0';
2899 type = stktable_get_data_type(cw);
2900 if (type < 0) {
2901 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2902 file, linenum, args[0], cw);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
Willy Tarreauac782882010-06-20 10:41:54 +02002906
2907 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2908 switch (err) {
2909 case PE_NONE: break;
2910 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002911 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002914 break;
2915
2916 case PE_ARG_MISSING:
2917 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2918 file, linenum, args[0], cw);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921
2922 case PE_ARG_NOT_USED:
2923 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2924 file, linenum, args[0], cw);
2925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
2927
2928 default:
2929 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2930 file, linenum, args[0], cw);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002933 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002934 }
2935 myidx++;
2936 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002937 else {
2938 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2939 file, linenum, args[myidx]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 }
2944
2945 if (!curproxy->table.size) {
2946 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2947 file, linenum);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951
2952 if (curproxy->table.type == (unsigned int)-1) {
2953 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2954 file, linenum);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958 }
2959 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002961 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 int myidx = 0;
2963 const char *name = NULL;
2964 int flags;
2965
2966 if (curproxy == &defproxy) {
2967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2973 err_code |= ERR_WARN;
2974 goto out;
2975 }
2976
2977 myidx++;
2978 if ((strcmp(args[myidx], "store") == 0) ||
2979 (strcmp(args[myidx], "store-request") == 0)) {
2980 myidx++;
2981 flags = STK_IS_STORE;
2982 }
2983 else if (strcmp(args[myidx], "store-response") == 0) {
2984 myidx++;
2985 flags = STK_IS_STORE | STK_ON_RSP;
2986 }
2987 else if (strcmp(args[myidx], "match") == 0) {
2988 myidx++;
2989 flags = STK_IS_MATCH;
2990 }
2991 else if (strcmp(args[myidx], "on") == 0) {
2992 myidx++;
2993 flags = STK_IS_MATCH | STK_IS_STORE;
2994 }
2995 else {
2996 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000
3001 if (*(args[myidx]) == 0) {
3002 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003007 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003008 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003009 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
3013
3014 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003015 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003016 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3017 file, linenum, args[0], expr->fetch->kw);
3018 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003019 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 goto out;
3021 }
3022 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003023 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3025 file, linenum, args[0], expr->fetch->kw);
3026 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003027 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 goto out;
3029 }
3030 }
3031
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003032 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3033 if (expr->fetch->cap & SMP_CAP_L7)
3034 curproxy->acl_requires |= ACL_USE_L7_ANY;
3035
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 if (strcmp(args[myidx], "table") == 0) {
3037 myidx++;
3038 name = args[myidx++];
3039 }
3040
Willy Tarreauef6494c2010-01-28 17:12:36 +01003041 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003042 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3043 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3044 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003046 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003047 goto out;
3048 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003050 else if (*(args[myidx])) {
3051 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3052 file, linenum, args[0], args[myidx]);
3053 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003054 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003055 goto out;
3056 }
Emeric Brun97679e72010-09-23 17:56:44 +02003057 if (flags & STK_ON_RSP)
3058 err_code |= warnif_cond_requires_req(cond, file, linenum);
3059 else
3060 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003061
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3063 rule->cond = cond;
3064 rule->expr = expr;
3065 rule->flags = flags;
3066 rule->table.name = name ? strdup(name) : NULL;
3067 LIST_INIT(&rule->list);
3068 if (flags & STK_ON_RSP)
3069 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3070 else
3071 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003074 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003075 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003076
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3078 curproxy->uri_auth = NULL; /* we must detach from the default config */
3079
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003080 if (!*args[1]) {
3081 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003082 } else if (!strcmp(args[1], "admin")) {
3083 struct stats_admin_rule *rule;
3084
3085 if (curproxy == &defproxy) {
3086 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
3089 }
3090
3091 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3092 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
3095 }
3096
3097 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3098 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3099 file, linenum, args[0], args[1]);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003103 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3104 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3105 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
3108 }
3109
3110 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3111
3112 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3113 rule->cond = cond;
3114 LIST_INIT(&rule->list);
3115 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } else if (!strcmp(args[1], "uri")) {
3117 if (*(args[2]) == 0) {
3118 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_ABORT;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
3126 } else if (!strcmp(args[1], "realm")) {
3127 if (*(args[2]) == 0) {
3128 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3132 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003133 err_code |= ERR_ALERT | ERR_ABORT;
3134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003136 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003137 unsigned interval;
3138
3139 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3140 if (err) {
3141 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3142 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_FATAL;
3144 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003145 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02003149 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003150 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003151 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003152
3153 if (curproxy == &defproxy) {
3154 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158
3159 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3161 err_code |= ERR_ALERT | ERR_ABORT;
3162 goto out;
3163 }
3164
Willy Tarreauff011f22011-01-06 17:51:27 +01003165 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3166 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003167 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3168 file, linenum, args[0]);
3169 err_code |= ERR_WARN;
3170 }
3171
Willy Tarreauff011f22011-01-06 17:51:27 +01003172 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003173
Willy Tarreauff011f22011-01-06 17:51:27 +01003174 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003175 err_code |= ERR_ALERT | ERR_ABORT;
3176 goto out;
3177 }
3178
Willy Tarreauff011f22011-01-06 17:51:27 +01003179 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3180 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003181
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 } else if (!strcmp(args[1], "auth")) {
3183 if (*(args[2]) == 0) {
3184 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_ALERT | ERR_FATAL;
3186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3188 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_ABORT;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
3192 } else if (!strcmp(args[1], "scope")) {
3193 if (*(args[2]) == 0) {
3194 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
3202 } else if (!strcmp(args[1], "enable")) {
3203 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_ABORT;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003208 } else if (!strcmp(args[1], "hide-version")) {
3209 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3210 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_ABORT;
3212 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003213 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003214 } else if (!strcmp(args[1], "show-legends")) {
3215 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3216 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3217 err_code |= ERR_ALERT | ERR_ABORT;
3218 goto out;
3219 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003220 } else if (!strcmp(args[1], "show-node")) {
3221
3222 if (*args[2]) {
3223 int i;
3224 char c;
3225
3226 for (i=0; args[2][i]; i++) {
3227 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003228 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3229 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003230 break;
3231 }
3232
3233 if (!i || args[2][i]) {
3234 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3235 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3236 file, linenum, args[0], args[1]);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240 }
3241
3242 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3243 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3244 err_code |= ERR_ALERT | ERR_ABORT;
3245 goto out;
3246 }
3247 } else if (!strcmp(args[1], "show-desc")) {
3248 char *desc = NULL;
3249
3250 if (*args[2]) {
3251 int i, len=0;
3252 char *d;
3253
3254 for(i=2; *args[i]; i++)
3255 len += strlen(args[i])+1;
3256
3257 desc = d = (char *)calloc(1, len);
3258
3259 d += sprintf(d, "%s", args[2]);
3260 for(i=3; *args[i]; i++)
3261 d += sprintf(d, " %s", args[i]);
3262 }
3263
3264 if (!*args[2] && !global.desc)
3265 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3266 file, linenum, args[1]);
3267 else {
3268 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3269 free(desc);
3270 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3271 err_code |= ERR_ALERT | ERR_ABORT;
3272 goto out;
3273 }
3274 free(desc);
3275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003277stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003278 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 +01003279 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 }
3284 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003285 int optnum;
3286
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003287 if (*(args[1]) == '\0') {
3288 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003293
3294 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3295 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003296 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3297 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3298 file, linenum, cfg_opts[optnum].name);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301 }
Willy Tarreau93893792009-07-23 13:19:11 +02003302 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3303 err_code |= ERR_WARN;
3304 goto out;
3305 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003306
Willy Tarreau3842f002009-06-14 11:39:52 +02003307 curproxy->no_options &= ~cfg_opts[optnum].val;
3308 curproxy->options &= ~cfg_opts[optnum].val;
3309
3310 switch (kwm) {
3311 case KWM_STD:
3312 curproxy->options |= cfg_opts[optnum].val;
3313 break;
3314 case KWM_NO:
3315 curproxy->no_options |= cfg_opts[optnum].val;
3316 break;
3317 case KWM_DEF: /* already cleared */
3318 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003319 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003320
Willy Tarreau93893792009-07-23 13:19:11 +02003321 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322 }
3323 }
3324
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003325 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3326 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003327 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3328 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3329 file, linenum, cfg_opts2[optnum].name);
3330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
3332 }
Willy Tarreau93893792009-07-23 13:19:11 +02003333 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3334 err_code |= ERR_WARN;
3335 goto out;
3336 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003337
Willy Tarreau3842f002009-06-14 11:39:52 +02003338 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3339 curproxy->options2 &= ~cfg_opts2[optnum].val;
3340
3341 switch (kwm) {
3342 case KWM_STD:
3343 curproxy->options2 |= cfg_opts2[optnum].val;
3344 break;
3345 case KWM_NO:
3346 curproxy->no_options2 |= cfg_opts2[optnum].val;
3347 break;
3348 case KWM_DEF: /* already cleared */
3349 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003350 }
Willy Tarreau93893792009-07-23 13:19:11 +02003351 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003352 }
3353 }
3354
Willy Tarreau3842f002009-06-14 11:39:52 +02003355 if (kwm != KWM_STD) {
3356 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003357 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003360 }
3361
Emeric Brun3a058f32009-06-30 18:26:00 +02003362 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003363 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003365 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 if (*(args[2]) != '\0') {
3367 if (!strcmp(args[2], "clf")) {
3368 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003369 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003370 } else {
3371 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003372 err_code |= ERR_ALERT | ERR_FATAL;
3373 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003374 }
3375 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003376 if (curproxy->logformat_string != default_http_log_format &&
3377 curproxy->logformat_string != default_tcp_log_format &&
3378 curproxy->logformat_string != clf_http_log_format)
3379 free(curproxy->logformat_string);
3380 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003381 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003382 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003384 if (curproxy->logformat_string != default_http_log_format &&
3385 curproxy->logformat_string != default_tcp_log_format &&
3386 curproxy->logformat_string != clf_http_log_format)
3387 free(curproxy->logformat_string);
3388 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 else if (!strcmp(args[1], "tcpka")) {
3391 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003392 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003394
3395 if (curproxy->cap & PR_CAP_FE)
3396 curproxy->options |= PR_O_TCP_CLI_KA;
3397 if (curproxy->cap & PR_CAP_BE)
3398 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
3400 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003401 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003402 err_code |= ERR_WARN;
3403
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003405 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003406 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003407 curproxy->options2 &= ~PR_O2_CHK_ANY;
3408 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003409 if (!*args[2]) { /* no argument */
3410 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3411 curproxy->check_len = strlen(DEF_CHECK_REQ);
3412 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003413 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 curproxy->check_req = (char *)malloc(reqlen);
3415 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003416 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003418 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 if (*args[4])
3420 reqlen += strlen(args[4]);
3421 else
3422 reqlen += strlen("HTTP/1.0");
3423
3424 curproxy->check_req = (char *)malloc(reqlen);
3425 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003426 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003428 }
3429 else if (!strcmp(args[1], "ssl-hello-chk")) {
3430 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003431 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003432 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003433
Willy Tarreaua534fea2008-08-03 12:19:50 +02003434 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003435 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003436 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003437 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 }
Willy Tarreau23677902007-05-08 23:50:35 +02003439 else if (!strcmp(args[1], "smtpchk")) {
3440 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003441 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003442 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003443 curproxy->options2 &= ~PR_O2_CHK_ANY;
3444 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003445
3446 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3447 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3448 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3449 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3450 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3451 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3452 curproxy->check_req = (char *)malloc(reqlen);
3453 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3454 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3455 } else {
3456 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3457 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3458 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3459 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3460 }
3461 }
3462 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003463 else if (!strcmp(args[1], "lb-agent-chk")) {
3464 /* use dynmaic health check */
3465 free(curproxy->check_req);
3466 curproxy->check_req = NULL;
3467 curproxy->options2 &= ~PR_O2_CHK_ANY;
3468 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3469 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003470 else if (!strcmp(args[1], "pgsql-check")) {
3471 /* use PostgreSQL request to check servers' health */
3472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3473 err_code |= ERR_WARN;
3474
3475 free(curproxy->check_req);
3476 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003477 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003478 curproxy->options2 |= PR_O2_PGSQL_CHK;
3479
3480 if (*(args[2])) {
3481 int cur_arg = 2;
3482
3483 while (*(args[cur_arg])) {
3484 if (strcmp(args[cur_arg], "user") == 0) {
3485 char * packet;
3486 uint32_t packet_len;
3487 uint32_t pv;
3488
3489 /* suboption header - needs additional argument for it */
3490 if (*(args[cur_arg+1]) == 0) {
3491 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3492 file, linenum, args[0], args[1], args[cur_arg]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496
3497 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3498 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3499 pv = htonl(0x30000); /* protocol version 3.0 */
3500
3501 packet = (char*) calloc(1, packet_len);
3502
3503 memcpy(packet + 4, &pv, 4);
3504
3505 /* copy "user" */
3506 memcpy(packet + 8, "user", 4);
3507
3508 /* copy username */
3509 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3510
3511 free(curproxy->check_req);
3512 curproxy->check_req = packet;
3513 curproxy->check_len = packet_len;
3514
3515 packet_len = htonl(packet_len);
3516 memcpy(packet, &packet_len, 4);
3517 cur_arg += 2;
3518 } else {
3519 /* unknown suboption - catchall */
3520 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3521 file, linenum, args[0], args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 } /* end while loop */
3526 }
3527 }
3528
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003529 else if (!strcmp(args[1], "redis-check")) {
3530 /* use REDIS PING request to check servers' health */
3531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3532 err_code |= ERR_WARN;
3533
3534 free(curproxy->check_req);
3535 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003536 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003537 curproxy->options2 |= PR_O2_REDIS_CHK;
3538
3539 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3540 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3541 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3542 }
3543
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003544 else if (!strcmp(args[1], "mysql-check")) {
3545 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3547 err_code |= ERR_WARN;
3548
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003549 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003550 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003551 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003552 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003553
3554 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3555 * const char mysql40_client_auth_pkt[] = {
3556 * "\x0e\x00\x00" // packet length
3557 * "\x01" // packet number
3558 * "\x00\x00" // client capabilities
3559 * "\x00\x00\x01" // max packet
3560 * "haproxy\x00" // username (null terminated string)
3561 * "\x00" // filler (always 0x00)
3562 * "\x01\x00\x00" // packet length
3563 * "\x00" // packet number
3564 * "\x01" // COM_QUIT command
3565 * };
3566 */
3567
3568 if (*(args[2])) {
3569 int cur_arg = 2;
3570
3571 while (*(args[cur_arg])) {
3572 if (strcmp(args[cur_arg], "user") == 0) {
3573 char *mysqluser;
3574 int packetlen, reqlen, userlen;
3575
3576 /* suboption header - needs additional argument for it */
3577 if (*(args[cur_arg+1]) == 0) {
3578 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3579 file, linenum, args[0], args[1], args[cur_arg]);
3580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
3582 }
3583 mysqluser = args[cur_arg + 1];
3584 userlen = strlen(mysqluser);
3585 packetlen = userlen + 7;
3586 reqlen = packetlen + 9;
3587
3588 free(curproxy->check_req);
3589 curproxy->check_req = (char *)calloc(1, reqlen);
3590 curproxy->check_len = reqlen;
3591
3592 snprintf(curproxy->check_req, 4, "%c%c%c",
3593 ((unsigned char) packetlen & 0xff),
3594 ((unsigned char) (packetlen >> 8) & 0xff),
3595 ((unsigned char) (packetlen >> 16) & 0xff));
3596
3597 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003598 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003599 curproxy->check_req[8] = 1;
3600 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3601 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3602 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3603 cur_arg += 2;
3604 } else {
3605 /* unknown suboption - catchall */
3606 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3607 file, linenum, args[0], args[1]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611 } /* end while loop */
3612 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003613 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003614 else if (!strcmp(args[1], "ldap-check")) {
3615 /* use LDAP request to check servers' health */
3616 free(curproxy->check_req);
3617 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003618 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003619 curproxy->options2 |= PR_O2_LDAP_CHK;
3620
3621 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3622 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3623 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3624 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003625 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003626 int cur_arg;
3627
3628 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3629 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003630 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003631
Willy Tarreau87cf5142011-08-19 22:57:24 +02003632 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003633
3634 free(curproxy->fwdfor_hdr_name);
3635 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3636 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3637
3638 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3639 cur_arg = 2;
3640 while (*(args[cur_arg])) {
3641 if (!strcmp(args[cur_arg], "except")) {
3642 /* suboption except - needs additional argument for it */
3643 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3644 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3645 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003648 }
3649 /* flush useless bits */
3650 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003651 cur_arg += 2;
3652 } else if (!strcmp(args[cur_arg], "header")) {
3653 /* suboption header - needs additional argument for it */
3654 if (*(args[cur_arg+1]) == 0) {
3655 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3656 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003659 }
3660 free(curproxy->fwdfor_hdr_name);
3661 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3662 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3663 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003664 } else if (!strcmp(args[cur_arg], "if-none")) {
3665 curproxy->options &= ~PR_O_FF_ALWAYS;
3666 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003667 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003668 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003669 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003670 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003673 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003674 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003675 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003676 else if (!strcmp(args[1], "originalto")) {
3677 int cur_arg;
3678
3679 /* insert x-original-to field, but not for the IP address listed as an except.
3680 * set default options (ie: bitfield, header name, etc)
3681 */
3682
3683 curproxy->options |= PR_O_ORGTO;
3684
3685 free(curproxy->orgto_hdr_name);
3686 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3687 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3688
Willy Tarreau87cf5142011-08-19 22:57:24 +02003689 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003690 cur_arg = 2;
3691 while (*(args[cur_arg])) {
3692 if (!strcmp(args[cur_arg], "except")) {
3693 /* suboption except - needs additional argument for it */
3694 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3695 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3696 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003699 }
3700 /* flush useless bits */
3701 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3702 cur_arg += 2;
3703 } else if (!strcmp(args[cur_arg], "header")) {
3704 /* suboption header - needs additional argument for it */
3705 if (*(args[cur_arg+1]) == 0) {
3706 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3707 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003710 }
3711 free(curproxy->orgto_hdr_name);
3712 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3713 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3714 cur_arg += 2;
3715 } else {
3716 /* unknown suboption - catchall */
3717 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3718 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003721 }
3722 } /* end while loop */
3723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 else {
3725 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003728 }
Willy Tarreau93893792009-07-23 13:19:11 +02003729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003731 else if (!strcmp(args[0], "default_backend")) {
3732 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003734
3735 if (*(args[1]) == 0) {
3736 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003739 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003740 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003741 curproxy->defbe.name = strdup(args[1]);
3742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003744 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003746
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003747 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 /* enable reconnections to dispatch */
3751 curproxy->options |= PR_O_REDISP;
3752 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003753 else if (!strcmp(args[0], "http-check")) {
3754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003756
3757 if (strcmp(args[1], "disable-on-404") == 0) {
3758 /* enable a graceful server shutdown on an HTTP 404 response */
3759 curproxy->options |= PR_O_DISABLE404;
3760 }
Willy Tarreauef781042010-01-27 11:53:01 +01003761 else if (strcmp(args[1], "send-state") == 0) {
3762 /* enable emission of the apparent state of a server in HTTP checks */
3763 curproxy->options2 |= PR_O2_CHK_SNDST;
3764 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003765 else if (strcmp(args[1], "expect") == 0) {
3766 const char *ptr_arg;
3767 int cur_arg;
3768
3769 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3770 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774
3775 cur_arg = 2;
3776 /* consider exclamation marks, sole or at the beginning of a word */
3777 while (*(ptr_arg = args[cur_arg])) {
3778 while (*ptr_arg == '!') {
3779 curproxy->options2 ^= PR_O2_EXP_INV;
3780 ptr_arg++;
3781 }
3782 if (*ptr_arg)
3783 break;
3784 cur_arg++;
3785 }
3786 /* now ptr_arg points to the beginning of a word past any possible
3787 * exclamation mark, and cur_arg is the argument which holds this word.
3788 */
3789 if (strcmp(ptr_arg, "status") == 0) {
3790 if (!*(args[cur_arg + 1])) {
3791 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3792 file, linenum, args[0], args[1], ptr_arg);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003797 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003798 curproxy->expect_str = strdup(args[cur_arg + 1]);
3799 }
3800 else if (strcmp(ptr_arg, "string") == 0) {
3801 if (!*(args[cur_arg + 1])) {
3802 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3803 file, linenum, args[0], args[1], ptr_arg);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
3807 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003808 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003809 curproxy->expect_str = strdup(args[cur_arg + 1]);
3810 }
3811 else if (strcmp(ptr_arg, "rstatus") == 0) {
3812 if (!*(args[cur_arg + 1])) {
3813 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3814 file, linenum, args[0], args[1], ptr_arg);
3815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
3817 }
3818 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003819 free(curproxy->expect_str);
3820 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3821 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003822 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3823 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3824 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3825 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
3828 }
3829 }
3830 else if (strcmp(ptr_arg, "rstring") == 0) {
3831 if (!*(args[cur_arg + 1])) {
3832 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3833 file, linenum, args[0], args[1], ptr_arg);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003838 free(curproxy->expect_str);
3839 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3840 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003841 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3842 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3843 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3844 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 }
3849 else {
3850 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3851 file, linenum, args[0], args[1], ptr_arg);
3852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
3854 }
3855 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003856 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003857 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 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003860 }
3861 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003863 if (curproxy == &defproxy) {
3864 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003867 }
3868
Willy Tarreaub80c2302007-11-30 20:51:32 +01003869 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003871
3872 if (strcmp(args[1], "fail") == 0) {
3873 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003874 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3876 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003879 }
3880
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003881 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3882 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3883 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003886 }
3887 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3888 }
3889 else {
3890 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02003895#ifdef TPROXY
3896 else if (!strcmp(args[0], "transparent")) {
3897 /* enable transparent proxy connections */
3898 curproxy->options |= PR_O_TRANSP;
3899 }
3900#endif
3901 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003904
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 if (*(args[1]) == 0) {
3906 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
3910 curproxy->maxconn = atol(args[1]);
3911 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003912 else if (!strcmp(args[0], "backlog")) { /* backlog */
3913 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003915
3916 if (*(args[1]) == 0) {
3917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003920 }
3921 curproxy->backlog = atol(args[1]);
3922 }
Willy Tarreau86034312006-12-29 00:10:33 +01003923 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003924 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003926
Willy Tarreau86034312006-12-29 00:10:33 +01003927 if (*(args[1]) == 0) {
3928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003931 }
3932 curproxy->fullconn = atol(args[1]);
3933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3935 if (*(args[1]) == 0) {
3936 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003940 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3941 if (err) {
3942 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3943 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003946 }
3947 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003950 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003951 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003952 char *err_msg = NULL;
3953 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003954
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 if (curproxy == &defproxy) {
3956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003960 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003961 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003962
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003963 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003964 if (!sk) {
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003965 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 free(err_msg);
3968 goto out;
3969 }
3970 free(err_msg);
3971
3972 proto = protocol_by_family(sk->ss_family);
3973 if (!proto || !proto->connect) {
3974 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3975 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003976 err_code |= ERR_ALERT | ERR_FATAL;
3977 goto out;
3978 }
3979
3980 if (port1 != port2) {
3981 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3982 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003986
3987 if (!port1) {
3988 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3989 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003993
Willy Tarreaud5191e72010-02-09 20:50:45 +01003994 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003995 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
3997 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004000
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004001 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4002 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004007 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4008 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4009 err_code |= ERR_WARN;
4010
4011 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4012 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4013 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4014 }
4015 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4016 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4017 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4018 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004019 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4020 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4021 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4022 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004023 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004024 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 short realport = 0;
4032 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004034 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004039 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004040 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041
4042 if (!*args[2]) {
4043 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004048
4049 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004050 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004051 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4052 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004055 }
4056
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004058 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004059 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004060 char *err_msg = NULL;
4061 struct protocol *proto;
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 Tarreau4217a7d2013-03-06 20:04:27 +01004091 sk = str2sa_range(args[2], &port1, &port2, &err_msg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004092 if (!sk) {
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004093 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 free(err_msg);
4096 goto out;
4097 }
4098 free(err_msg);
4099
4100 proto = protocol_by_family(sk->ss_family);
4101 if (!proto || !proto->connect) {
4102 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4103 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004107
4108 if (!port1 || !port2) {
4109 /* no port specified, +offset, -offset */
4110 newsrv->state |= SRV_MAPPORTS;
4111 }
4112 else if (port1 != port2) {
4113 /* port range */
4114 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4115 file, linenum, args[0], args[1], args[2]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119 else {
4120 /* used by checks */
4121 realport = port1;
4122 }
4123
Willy Tarreaud5191e72010-02-09 20:50:45 +01004124 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004125 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4126 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004127
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004128 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004129 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4130 file, linenum, newsrv->addr.ss_family, args[2]);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004134
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004135 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004136 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004137 newsrv->inter = curproxy->defsrv.inter;
4138 newsrv->fastinter = curproxy->defsrv.fastinter;
4139 newsrv->downinter = curproxy->defsrv.downinter;
4140 newsrv->rise = curproxy->defsrv.rise;
4141 newsrv->fall = curproxy->defsrv.fall;
4142 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4143 newsrv->minconn = curproxy->defsrv.minconn;
4144 newsrv->maxconn = curproxy->defsrv.maxconn;
4145 newsrv->slowstart = curproxy->defsrv.slowstart;
4146 newsrv->onerror = curproxy->defsrv.onerror;
4147 newsrv->consecutive_errors_limit
4148 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004149#ifdef OPENSSL
4150 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4151#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004152 newsrv->uweight = newsrv->iweight
4153 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004155 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 cur_arg = 3;
4158 } else {
4159 newsrv = &curproxy->defsrv;
4160 cur_arg = 1;
4161 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004162
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004164 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 newsrv->cookie = strdup(args[cur_arg + 1]);
4166 newsrv->cklen = strlen(args[cur_arg + 1]);
4167 cur_arg += 2;
4168 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004169 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004170 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4171 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4172 cur_arg += 2;
4173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004175 if (!*args[cur_arg + 1]) {
4176 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4177 file, linenum, args[cur_arg]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004183 if (newsrv->rise <= 0) {
4184 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4185 file, linenum, args[cur_arg]);
4186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
4188 }
4189
Willy Tarreau96839092010-03-29 10:02:24 +02004190 if (newsrv->health)
4191 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 cur_arg += 2;
4193 }
4194 else if (!strcmp(args[cur_arg], "fall")) {
4195 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004196
4197 if (!*args[cur_arg + 1]) {
4198 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4199 file, linenum, args[cur_arg]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
4203
4204 if (newsrv->fall <= 0) {
4205 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4206 file, linenum, args[cur_arg]);
4207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 cur_arg += 2;
4212 }
4213 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004214 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4215 if (err) {
4216 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4217 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004220 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004221 if (val <= 0) {
4222 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4223 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004226 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004227 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 cur_arg += 2;
4229 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004230 else if (!strcmp(args[cur_arg], "fastinter")) {
4231 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4232 if (err) {
4233 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4234 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004237 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004238 if (val <= 0) {
4239 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4240 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004243 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004244 newsrv->fastinter = val;
4245 cur_arg += 2;
4246 }
4247 else if (!strcmp(args[cur_arg], "downinter")) {
4248 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4249 if (err) {
4250 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4251 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004254 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004255 if (val <= 0) {
4256 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4257 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004260 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004261 newsrv->downinter = val;
4262 cur_arg += 2;
4263 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004264 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004265 struct sockaddr_storage *sk;
4266 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004267 char *err_msg = NULL;
4268 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004269
Willy Tarreau1a20b142013-03-06 18:05:34 +01004270 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &err_msg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004271 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004272 Alert("parsing [%s:%d] : '%s' : %s\n",
4273 file, linenum, args[cur_arg], err_msg);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 free(err_msg);
4276 goto out;
4277 }
4278 free(err_msg);
4279
4280 proto = protocol_by_family(sk->ss_family);
4281 if (!proto || !proto->connect) {
4282 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004283 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004287
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004288 if (port1 != port2) {
4289 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4290 file, linenum, args[cur_arg], args[cur_arg + 1]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004295 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004296 cur_arg += 2;
4297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004299 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 cur_arg += 2;
4301 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004302 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 newsrv->state |= SRV_BACKUP;
4304 cur_arg ++;
4305 }
Simon Hormanfa461682011-06-25 09:39:49 +09004306 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4307 newsrv->state |= SRV_NON_STICK;
4308 cur_arg ++;
4309 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004310 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4311 newsrv->state |= SRV_SEND_PROXY;
4312 cur_arg ++;
4313 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004314 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4315 newsrv->check.send_proxy = 1;
4316 cur_arg ++;
4317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318 else if (!strcmp(args[cur_arg], "weight")) {
4319 int w;
4320 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004321 if (w < 0 || w > 256) {
4322 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004327 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 cur_arg += 2;
4329 }
4330 else if (!strcmp(args[cur_arg], "minconn")) {
4331 newsrv->minconn = atol(args[cur_arg + 1]);
4332 cur_arg += 2;
4333 }
4334 else if (!strcmp(args[cur_arg], "maxconn")) {
4335 newsrv->maxconn = atol(args[cur_arg + 1]);
4336 cur_arg += 2;
4337 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004338 else if (!strcmp(args[cur_arg], "maxqueue")) {
4339 newsrv->maxqueue = atol(args[cur_arg + 1]);
4340 cur_arg += 2;
4341 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004342 else if (!strcmp(args[cur_arg], "slowstart")) {
4343 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004344 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004345 if (err) {
4346 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4347 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004350 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004351 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004352 cur_arg += 2;
4353 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004354 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004355
4356 if (!*args[cur_arg + 1]) {
4357 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004361 }
4362
4363 newsrv->trackit = strdup(args[cur_arg + 1]);
4364
4365 cur_arg += 2;
4366 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004367 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 global.maxsock++;
4369 do_check = 1;
4370 cur_arg += 1;
4371 }
Willy Tarreau96839092010-03-29 10:02:24 +02004372 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4373 newsrv->state |= SRV_MAINTAIN;
4374 newsrv->state &= ~SRV_RUNNING;
4375 newsrv->health = 0;
4376 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004377 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004378 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004379 if (!strcmp(args[cur_arg + 1], "none"))
4380 newsrv->observe = HANA_OBS_NONE;
4381 else if (!strcmp(args[cur_arg + 1], "layer4"))
4382 newsrv->observe = HANA_OBS_LAYER4;
4383 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4384 if (curproxy->mode != PR_MODE_HTTP) {
4385 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4386 file, linenum, args[cur_arg + 1]);
4387 err_code |= ERR_ALERT;
4388 }
4389 newsrv->observe = HANA_OBS_LAYER7;
4390 }
4391 else {
4392 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004393 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004394 file, linenum, args[cur_arg], args[cur_arg + 1]);
4395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398
4399 cur_arg += 2;
4400 }
4401 else if (!strcmp(args[cur_arg], "on-error")) {
4402 if (!strcmp(args[cur_arg + 1], "fastinter"))
4403 newsrv->onerror = HANA_ONERR_FASTINTER;
4404 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4405 newsrv->onerror = HANA_ONERR_FAILCHK;
4406 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4407 newsrv->onerror = HANA_ONERR_SUDDTH;
4408 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4409 newsrv->onerror = HANA_ONERR_MARKDWN;
4410 else {
4411 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004412 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004413 file, linenum, args[cur_arg], args[cur_arg + 1]);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
4417
4418 cur_arg += 2;
4419 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004420 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4421 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4422 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4423 else {
4424 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4425 file, linenum, args[cur_arg], args[cur_arg + 1]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429
4430 cur_arg += 2;
4431 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004432 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4433 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4434 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4435 else {
4436 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4437 file, linenum, args[cur_arg], args[cur_arg + 1]);
4438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
4440 }
4441
4442 cur_arg += 2;
4443 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004444 else if (!strcmp(args[cur_arg], "error-limit")) {
4445 if (!*args[cur_arg + 1]) {
4446 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4447 file, linenum, args[cur_arg]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
4451
4452 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4453
4454 if (newsrv->consecutive_errors_limit <= 0) {
4455 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4456 file, linenum, args[cur_arg]);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004460 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004461 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004462 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004463 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004464 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004465 char *err_msg = NULL;
4466 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004467
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004469 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4470 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004474
Willy Tarreauef9a3602012-12-08 22:29:20 +01004475 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004476 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &err_msg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004477 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004478 Alert("parsing [%s:%d] : '%s %s' : %s\n",
4479 file, linenum, args[cur_arg], args[cur_arg+1], err_msg);
4480 err_code |= ERR_ALERT | ERR_FATAL;
4481 free(err_msg);
4482 goto out;
4483 }
4484 free(err_msg);
4485
4486 proto = protocol_by_family(sk->ss_family);
4487 if (!proto || !proto->connect) {
4488 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4489 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
4492 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004493
Willy Tarreauef9a3602012-12-08 22:29:20 +01004494 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004495
4496 if (port_low != port_high) {
4497 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004498
4499 if (!port_low || !port_high) {
4500 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4501 file, linenum, args[cur_arg], args[cur_arg + 1]);
4502 err_code |= ERR_ALERT | ERR_FATAL;
4503 goto out;
4504 }
4505
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004506 if (port_low <= 0 || port_low > 65535 ||
4507 port_high <= 0 || port_high > 65535 ||
4508 port_low > port_high) {
4509 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4510 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004513 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004514 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4515 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4516 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004517 }
4518
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004520 while (*(args[cur_arg])) {
4521 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004522#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4523#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004524 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4526 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004529 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004530#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004531 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004532 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004533 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004536 }
4537 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004538 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4539 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004540 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004541 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4542 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004543 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4544 char *name, *end;
4545
4546 name = args[cur_arg+1] + 7;
4547 while (isspace(*name))
4548 name++;
4549
4550 end = name;
4551 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4552 end++;
4553
Willy Tarreauef9a3602012-12-08 22:29:20 +01004554 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4555 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4556 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4557 newsrv->conn_src.bind_hdr_len = end - name;
4558 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4559 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4560 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004561
4562 /* now look for an occurrence number */
4563 while (isspace(*end))
4564 end++;
4565 if (*end == ',') {
4566 end++;
4567 name = end;
4568 if (*end == '-')
4569 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004570 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004571 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004572 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004573 }
4574
Willy Tarreauef9a3602012-12-08 22:29:20 +01004575 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004576 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4577 " occurrences values smaller than %d.\n",
4578 file, linenum, MAX_HDR_HISTORY);
4579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004582 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004583 struct sockaddr_storage *sk;
4584 int port1, port2;
4585
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004586 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &err_msg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004587 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004588 Alert("parsing [%s:%d] : '%s %s' : %s\n",
4589 file, linenum, args[cur_arg], args[cur_arg+1], err_msg);
4590 err_code |= ERR_ALERT | ERR_FATAL;
4591 free(err_msg);
4592 goto out;
4593 }
4594 free(err_msg);
4595
4596 proto = protocol_by_family(sk->ss_family);
4597 if (!proto || !proto->connect) {
4598 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4599 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004603
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004604 if (port1 != port2) {
4605 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4606 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004610 newsrv->conn_src.tproxy_addr = *sk;
4611 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004612 }
4613 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004614#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004615 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004616#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004617 cur_arg += 2;
4618 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004619#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004620 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004621 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004624#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4625 } /* "usesrc" */
4626
4627 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4628#ifdef SO_BINDTODEVICE
4629 if (!*args[cur_arg + 1]) {
4630 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4631 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004634 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004635 free(newsrv->conn_src.iface_name);
4636 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4637 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004638 global.last_checks |= LSTCHK_NETADM;
4639#else
4640 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4641 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004644#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004645 cur_arg += 2;
4646 continue;
4647 }
4648 /* this keyword in not an option of "source" */
4649 break;
4650 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004652 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004653 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4654 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004659 static int srv_dumped;
4660 struct srv_kw *kw;
4661 char *err;
4662
4663 kw = srv_find_kw(args[cur_arg]);
4664 if (kw) {
4665 char *err = NULL;
4666 int code;
4667
4668 if (!kw->parse) {
4669 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4670 file, linenum, args[0], args[1], args[cur_arg]);
4671 cur_arg += 1 + kw->skip ;
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675
4676 if (defsrv && !kw->default_ok) {
4677 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4678 file, linenum, args[0], args[1], args[cur_arg]);
4679 cur_arg += 1 + kw->skip ;
4680 err_code |= ERR_ALERT;
4681 continue;
4682 }
4683
4684 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4685 err_code |= code;
4686
4687 if (code) {
4688 if (err && *err) {
4689 indent_msg(&err, 2);
4690 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4691 }
4692 else
4693 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4694 file, linenum, args[0], args[1], args[cur_arg]);
4695 if (code & ERR_FATAL) {
4696 free(err);
4697 cur_arg += 1 + kw->skip;
4698 goto out;
4699 }
4700 }
4701 free(err);
4702 cur_arg += 1 + kw->skip;
4703 continue;
4704 }
4705
4706 err = NULL;
4707 if (!srv_dumped) {
4708 srv_dump_kws(&err);
4709 indent_msg(&err, 4);
4710 srv_dumped = 1;
4711 }
4712
4713 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4714 file, linenum, args[0], args[1], args[cur_arg],
4715 err ? " Registered keywords :" : "", err ? err : "");
4716 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004717
Willy Tarreau93893792009-07-23 13:19:11 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
4721 }
4722
4723 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004724 if (newsrv->trackit) {
4725 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4726 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004729 }
4730
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004731 /* If neither a port nor an addr was specified and no check transport
4732 * layer is forced, then the transport layer used by the checks is the
4733 * same as for the production traffic. Otherwise we use raw_sock by
4734 * default, unless one is specified.
4735 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004736 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004737#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004738 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004739#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004740 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4741 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004742 /* try to get the port from check.addr if check.port not set */
4743 if (!newsrv->check.port)
4744 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004745
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004746 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004747 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004748
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004749 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004750 /* not yet valid, because no port was set on
4751 * the server either. We'll check if we have
4752 * a known port on the first listener.
4753 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004754 struct listener *l;
4755
4756 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004757 newsrv->check.port = get_host_port(&l->addr);
4758 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004759 break;
4760 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004761 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004762 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4764 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004768
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004769 /* Allocate buffer for check requests... */
4770 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004771 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4772 err_code |= ERR_ALERT | ERR_ABORT;
4773 goto out;
4774 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004775 newsrv->check.bi->size = global.tune.chksize;
4776
4777 /* Allocate buffer for check responses... */
4778 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4779 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4780 err_code |= ERR_ALERT | ERR_ABORT;
4781 goto out;
4782 }
4783 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004784
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004785 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004786 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004787 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4788 err_code |= ERR_ALERT | ERR_ABORT;
4789 goto out;
4790 }
4791
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004792 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4793 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 newsrv->state |= SRV_CHECKED;
4795 }
4796
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004797 if (!defsrv) {
4798 if (newsrv->state & SRV_BACKUP)
4799 curproxy->srv_bck++;
4800 else
4801 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004802
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004803 newsrv->prev_state = newsrv->state;
4804 }
William Lallemanda73203e2012-03-12 12:48:57 +01004805 }
4806
4807 else if (strcmp(args[0], "unique-id-format") == 0) {
4808 if (!*(args[1])) {
4809 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812 }
William Lallemand3203ff42012-11-11 17:30:56 +01004813 if (*(args[2])) {
4814 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
4817 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004818 free(curproxy->uniqueid_format_string);
4819 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004820 }
William Lallemanda73203e2012-03-12 12:48:57 +01004821
4822 else if (strcmp(args[0], "unique-id-header") == 0) {
4823 if (!*(args[1])) {
4824 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
4827 }
4828 free(curproxy->header_unique_id);
4829 curproxy->header_unique_id = strdup(args[1]);
4830 }
4831
William Lallemand723b73a2012-02-08 16:37:49 +01004832 else if (strcmp(args[0], "log-format") == 0) {
4833 if (!*(args[1])) {
4834 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
William Lallemand3203ff42012-11-11 17:30:56 +01004838 if (*(args[2])) {
4839 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4840 err_code |= ERR_ALERT | ERR_FATAL;
4841 goto out;
4842 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004843
4844 if (curproxy->logformat_string != default_http_log_format &&
4845 curproxy->logformat_string != default_tcp_log_format &&
4846 curproxy->logformat_string != clf_http_log_format)
4847 free(curproxy->logformat_string);
4848 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
William Lallemand723b73a2012-02-08 16:37:49 +01004850
William Lallemand0f99e342011-10-12 17:50:54 +02004851 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4852 /* delete previous herited or defined syslog servers */
4853 struct logsrv *back;
4854
4855 if (*(args[1]) != 0) {
4856 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
4859 }
4860
William Lallemand723b73a2012-02-08 16:37:49 +01004861 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4862 LIST_DEL(&tmplogsrv->list);
4863 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004864 }
4865 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004867 struct logsrv *logsrv;
4868
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004870 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004871 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004872 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004873 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004874 LIST_INIT(&node->list);
4875 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
4878 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004879 struct sockaddr_storage *sk;
4880 int port1, port2;
4881 char *err_msg = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02004882
4883 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884
William Lallemand0f99e342011-10-12 17:50:54 +02004885 logsrv->facility = get_log_facility(args[2]);
4886 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 }
4892
William Lallemand0f99e342011-10-12 17:50:54 +02004893 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004895 logsrv->level = get_log_level(args[3]);
4896 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
4900
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
4902 }
4903
William Lallemand0f99e342011-10-12 17:50:54 +02004904 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004905 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004906 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004907 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004908 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
4911
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004912 }
4913 }
4914
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004915 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
4916 if (!sk) {
4917 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], err_msg);
4918 err_code |= ERR_ALERT | ERR_FATAL;
4919 free(err_msg);
4920 goto out;
4921 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004922
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004923 logsrv->addr = *sk;
4924 free(err_msg);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004925
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004926 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004927 if (port1 != port2) {
4928 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4929 file, linenum, args[0], args[1]);
4930 err_code |= ERR_ALERT | ERR_FATAL;
4931 goto out;
4932 }
4933
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004934 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004935 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
William Lallemand0f99e342011-10-12 17:50:54 +02004937
4938 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
4940 else {
4941 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4942 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 }
4947 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004949 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004950 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004951 char *err_msg = NULL;
4952 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953
Willy Tarreau977b8e42006-12-29 14:19:17 +01004954 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004956
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004958 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4959 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004963
4964 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004965 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4966 free(curproxy->conn_src.iface_name);
4967 curproxy->conn_src.iface_name = NULL;
4968 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004969
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004970 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004971 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004972 Alert("parsing [%s:%d] : '%s %s' : %s\n",
4973 file, linenum, args[0], args[1], err_msg);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 free(err_msg);
4976 goto out;
4977 }
4978 free(err_msg);
4979
4980 proto = protocol_by_family(sk->ss_family);
4981 if (!proto || !proto->connect) {
4982 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004983 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
4986 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004987
4988 if (port1 != port2) {
4989 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4990 file, linenum, args[0], args[1]);
4991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994
Willy Tarreauef9a3602012-12-08 22:29:20 +01004995 curproxy->conn_src.source_addr = *sk;
4996 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004997
4998 cur_arg = 2;
4999 while (*(args[cur_arg])) {
5000 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005001#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5002#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005003 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005004 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5005 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005008 }
5009#endif
5010 if (!*args[cur_arg + 1]) {
5011 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5012 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005015 }
5016
5017 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005018 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5019 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005020 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005021 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5022 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005023 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5024 char *name, *end;
5025
5026 name = args[cur_arg+1] + 7;
5027 while (isspace(*name))
5028 name++;
5029
5030 end = name;
5031 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5032 end++;
5033
Willy Tarreauef9a3602012-12-08 22:29:20 +01005034 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5035 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5036 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5037 curproxy->conn_src.bind_hdr_len = end - name;
5038 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5039 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5040 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005041
5042 /* now look for an occurrence number */
5043 while (isspace(*end))
5044 end++;
5045 if (*end == ',') {
5046 end++;
5047 name = end;
5048 if (*end == '-')
5049 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005050 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005051 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005052 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005053 }
5054
Willy Tarreauef9a3602012-12-08 22:29:20 +01005055 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005056 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5057 " occurrences values smaller than %d.\n",
5058 file, linenum, MAX_HDR_HISTORY);
5059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
5061 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005062 } else {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005063 struct sockaddr_storage *sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &err_msg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005064
Willy Tarreaud5191e72010-02-09 20:50:45 +01005065 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005066 Alert("parsing [%s:%d] : '%s %s' : %s\n",
5067 file, linenum, args[cur_arg], args[cur_arg+1], err_msg);
5068 err_code |= ERR_ALERT | ERR_FATAL;
5069 free(err_msg);
5070 goto out;
5071 }
5072 free(err_msg);
5073
5074 proto = protocol_by_family(sk->ss_family);
5075 if (!proto || !proto->connect) {
5076 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5077 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
5080 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005081
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005082 if (port1 != port2) {
5083 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5084 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005088 curproxy->conn_src.tproxy_addr = *sk;
5089 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005090 }
5091 global.last_checks |= LSTCHK_NETADM;
5092#if !defined(CONFIG_HAP_LINUX_TPROXY)
5093 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005094#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005095#else /* no TPROXY support */
5096 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005097 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005100#endif
5101 cur_arg += 2;
5102 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005103 }
5104
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005105 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5106#ifdef SO_BINDTODEVICE
5107 if (!*args[cur_arg + 1]) {
5108 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005112 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005113 free(curproxy->conn_src.iface_name);
5114 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5115 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005116 global.last_checks |= LSTCHK_NETADM;
5117#else
5118 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5119 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005122#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005123 cur_arg += 2;
5124 continue;
5125 }
5126 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005127 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005132 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5133 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5134 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145
5146 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005147 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005148 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
5152 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005154 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005155 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
5159 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005160 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005161 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005162 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
5166 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005167 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005168 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005169 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 }
5173 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005175 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005176 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005180 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005182 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005183 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005185 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005186 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005187 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005189 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005190 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005192 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005193 }
5194 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005196 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005197 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005198 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005199 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005207 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208
5209 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005210 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005211 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005213 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005214 }
5215 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005217 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005218 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005219 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
5222 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005224 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005225 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
5229 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005231 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005232 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
5236 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005238 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005239 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005240 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005243 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005244 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005245 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005246 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005248 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005251 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005252
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 if (curproxy == &defproxy) {
5254 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005258 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 if (*(args[1]) == 0) {
5262 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005266
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005267 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005268 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5269 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5270 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
5273 }
5274 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5275 }
5276 else if (*args[2]) {
5277 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5278 file, linenum, args[0], args[2]);
5279 err_code |= ERR_ALERT | ERR_FATAL;
5280 goto out;
5281 }
5282
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005283 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005284 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005285 wl->s = strdup(args[1]);
5286 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005287 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
5289 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5292 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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005296
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005298 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005299 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 }
5303 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005305 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
5310 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005312 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316 }
5317 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005321 err_code |= ERR_ALERT | ERR_FATAL;
5322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 }
5324
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005326 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005327 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
5331 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005333 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005334 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 }
5338 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005340 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 }
5345 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005346 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005347
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 if (curproxy == &defproxy) {
5349 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005353 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 if (*(args[1]) == 0) {
5357 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005362 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005363 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5364 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5365 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005366 err_code |= ERR_ALERT | ERR_FATAL;
5367 goto out;
5368 }
5369 err_code |= warnif_cond_requires_req(cond, file, linenum);
5370 }
5371 else if (*args[2]) {
5372 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5373 file, linenum, args[0], args[2]);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005378 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005379 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005380 wl->s = strdup(args[1]);
5381 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383 else if (!strcmp(args[0], "errorloc") ||
5384 !strcmp(args[0], "errorloc302") ||
5385 !strcmp(args[0], "errorloc303")) { /* error location */
5386 int errnum, errlen;
5387 char *err;
5388
Willy Tarreau977b8e42006-12-29 14:19:17 +01005389 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005390 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005391
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005393 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 }
5397
5398 errnum = atol(args[1]);
5399 if (!strcmp(args[0], "errorloc303")) {
5400 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5401 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5402 } else {
5403 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5404 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5405 }
5406
Willy Tarreau0f772532006-12-23 20:51:41 +01005407 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5408 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005409 chunk_destroy(&curproxy->errmsg[rc]);
5410 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005411 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005414
5415 if (rc >= HTTP_ERR_SIZE) {
5416 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5417 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 free(err);
5419 }
5420 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005421 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5422 int errnum, errlen, fd;
5423 char *err;
5424 struct stat stat;
5425
5426 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005427 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005428
5429 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005430 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005433 }
5434
5435 fd = open(args[2], O_RDONLY);
5436 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5437 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5438 file, linenum, args[2], args[1]);
5439 if (fd >= 0)
5440 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005443 }
5444
Willy Tarreau27a674e2009-08-17 07:23:33 +02005445 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005446 errlen = stat.st_size;
5447 } else {
5448 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005449 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005450 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005451 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005452 }
5453
5454 err = malloc(errlen); /* malloc() must succeed during parsing */
5455 errnum = read(fd, err, errlen);
5456 if (errnum != errlen) {
5457 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5458 file, linenum, args[2], args[1]);
5459 close(fd);
5460 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005461 err_code |= ERR_ALERT | ERR_FATAL;
5462 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005463 }
5464 close(fd);
5465
5466 errnum = atol(args[1]);
5467 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5468 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005469 chunk_destroy(&curproxy->errmsg[rc]);
5470 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005471 break;
5472 }
5473 }
5474
5475 if (rc >= HTTP_ERR_SIZE) {
5476 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5477 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005479 free(err);
5480 }
5481 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005482 else if (!strcmp(args[0], "compression")) {
5483 struct comp *comp;
5484 if (curproxy->comp == NULL) {
5485 comp = calloc(1, sizeof(struct comp));
5486 curproxy->comp = comp;
5487 } else {
5488 comp = curproxy->comp;
5489 }
5490
5491 if (!strcmp(args[1], "algo")) {
5492 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005493 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005494
William Lallemand82fe75c2012-10-23 10:25:10 +02005495 cur_arg = 2;
5496 if (!*args[cur_arg]) {
5497 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5498 file, linenum, args[0]);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502 while (*(args[cur_arg])) {
5503 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5504 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5505 file, linenum, args[0], args[cur_arg]);
5506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
5508 }
William Lallemand552df672012-11-07 13:21:47 +01005509 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5510 curproxy->comp->algos->end(&ctx);
5511 } else {
5512 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5513 file, linenum, args[0], args[cur_arg]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005517 cur_arg ++;
5518 continue;
5519 }
5520 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005521 else if (!strcmp(args[1], "offload")) {
5522 comp->offload = 1;
5523 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005524 else if (!strcmp(args[1], "type")) {
5525 int cur_arg;
5526 cur_arg = 2;
5527 if (!*args[cur_arg]) {
5528 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5529 file, linenum, args[0]);
5530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532 }
5533 while (*(args[cur_arg])) {
5534 comp_append_type(comp, args[cur_arg]);
5535 cur_arg ++;
5536 continue;
5537 }
5538 }
5539 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005540 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005541 file, linenum, args[0]);
5542 err_code |= ERR_ALERT | ERR_FATAL;
5543 goto out;
5544 }
5545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005547 struct cfg_kw_list *kwl;
5548 int index;
5549
5550 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5551 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5552 if (kwl->kw[index].section != CFG_LISTEN)
5553 continue;
5554 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5555 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005556 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005557 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005558 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005561 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005562 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005563 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_WARN;
5565 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005566 }
Willy Tarreau93893792009-07-23 13:19:11 +02005567 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005568 }
5569 }
5570 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005571
Willy Tarreau6daf3432008-01-22 16:44:08 +01005572 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 }
Willy Tarreau93893792009-07-23 13:19:11 +02005576 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005577 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005578 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579}
5580
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005581int
5582cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5583{
5584
5585 int err_code = 0;
5586 const char *err;
5587
5588 if (!strcmp(args[0], "userlist")) { /* new userlist */
5589 struct userlist *newul;
5590
5591 if (!*args[1]) {
5592 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5593 file, linenum, args[0]);
5594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
5596 }
5597
5598 err = invalid_char(args[1]);
5599 if (err) {
5600 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5601 file, linenum, *err, args[0], args[1]);
5602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
5605
5606 for (newul = userlist; newul; newul = newul->next)
5607 if (!strcmp(newul->name, args[1])) {
5608 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5609 file, linenum, args[1]);
5610 err_code |= ERR_WARN;
5611 goto out;
5612 }
5613
5614 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5615 if (!newul) {
5616 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5617 err_code |= ERR_ALERT | ERR_ABORT;
5618 goto out;
5619 }
5620
5621 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5622 newul->name = strdup(args[1]);
5623
5624 if (!newul->groupusers | !newul->name) {
5625 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5626 err_code |= ERR_ALERT | ERR_ABORT;
5627 goto out;
5628 }
5629
5630 newul->next = userlist;
5631 userlist = newul;
5632
5633 } else if (!strcmp(args[0], "group")) { /* new group */
5634 int cur_arg, i;
5635 const char *err;
5636
5637 if (!*args[1]) {
5638 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5639 file, linenum, args[0]);
5640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
5643
5644 err = invalid_char(args[1]);
5645 if (err) {
5646 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5647 file, linenum, *err, args[0], args[1]);
5648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
5650 }
5651
5652 for(i = 0; i < userlist->grpcnt; i++)
5653 if (!strcmp(userlist->groups[i], args[1])) {
5654 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5655 file, linenum, args[1], userlist->name);
5656 err_code |= ERR_ALERT;
5657 goto out;
5658 }
5659
5660 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5661 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5662 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
5665 }
5666
5667 cur_arg = 2;
5668
5669 while (*args[cur_arg]) {
5670 if (!strcmp(args[cur_arg], "users")) {
5671 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5672 cur_arg += 2;
5673 continue;
5674 } else {
5675 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5676 file, linenum, args[0]);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
5680 }
5681
5682 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5683 } else if (!strcmp(args[0], "user")) { /* new user */
5684 struct auth_users *newuser;
5685 int cur_arg;
5686
5687 if (!*args[1]) {
5688 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5689 file, linenum, args[0]);
5690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
5693
5694 for (newuser = userlist->users; newuser; newuser = newuser->next)
5695 if (!strcmp(newuser->user, args[1])) {
5696 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5697 file, linenum, args[1], userlist->name);
5698 err_code |= ERR_ALERT;
5699 goto out;
5700 }
5701
5702 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5703 if (!newuser) {
5704 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5705 err_code |= ERR_ALERT | ERR_ABORT;
5706 goto out;
5707 }
5708
5709 newuser->user = strdup(args[1]);
5710
5711 newuser->next = userlist->users;
5712 userlist->users = newuser;
5713
5714 cur_arg = 2;
5715
5716 while (*args[cur_arg]) {
5717 if (!strcmp(args[cur_arg], "password")) {
5718#ifndef CONFIG_HAP_CRYPT
5719 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5720 file, linenum);
5721 err_code |= ERR_ALERT;
5722#endif
5723 newuser->pass = strdup(args[cur_arg + 1]);
5724 cur_arg += 2;
5725 continue;
5726 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5727 newuser->pass = strdup(args[cur_arg + 1]);
5728 newuser->flags |= AU_O_INSECURE;
5729 cur_arg += 2;
5730 continue;
5731 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005732 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005733 cur_arg += 2;
5734 continue;
5735 } else {
5736 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5737 file, linenum, args[0]);
5738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
5741 }
5742 } else {
5743 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5744 err_code |= ERR_ALERT | ERR_FATAL;
5745 }
5746
5747out:
5748 return err_code;
5749}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750
5751/*
5752 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005753 * Returns the error code, 0 if OK, or any combination of :
5754 * - ERR_ABORT: must abort ASAP
5755 * - ERR_FATAL: we can continue parsing but not start the service
5756 * - ERR_WARN: a warning has been emitted
5757 * - ERR_ALERT: an alert has been emitted
5758 * Only the two first ones can stop processing, the two others are just
5759 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005761int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005763 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 FILE *f;
5765 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005767 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 if ((f=fopen(file,"r")) == NULL)
5770 return -1;
5771
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005772 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005773 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005774 char *end;
5775 char *args[MAX_LINE_ARGS + 1];
5776 char *line = thisline;
5777
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 linenum++;
5779
5780 end = line + strlen(line);
5781
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005782 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5783 /* Check if we reached the limit and the last char is not \n.
5784 * Watch out for the last line without the terminating '\n'!
5785 */
5786 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005787 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005788 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005789 }
5790
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005792 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793 line++;
5794
5795 arg = 0;
5796 args[arg] = line;
5797
5798 while (*line && arg < MAX_LINE_ARGS) {
5799 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5800 * C equivalent value. Other combinations left unchanged (eg: \1).
5801 */
5802 if (*line == '\\') {
5803 int skip = 0;
5804 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5805 *line = line[1];
5806 skip = 1;
5807 }
5808 else if (line[1] == 'r') {
5809 *line = '\r';
5810 skip = 1;
5811 }
5812 else if (line[1] == 'n') {
5813 *line = '\n';
5814 skip = 1;
5815 }
5816 else if (line[1] == 't') {
5817 *line = '\t';
5818 skip = 1;
5819 }
5820 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005821 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 unsigned char hex1, hex2;
5823 hex1 = toupper(line[2]) - '0';
5824 hex2 = toupper(line[3]) - '0';
5825 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5826 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5827 *line = (hex1<<4) + hex2;
5828 skip = 3;
5829 }
5830 else {
5831 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005832 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
5834 }
5835 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005836 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 end -= skip;
5838 }
5839 line++;
5840 }
5841 else if (*line == '#' || *line == '\n' || *line == '\r') {
5842 /* end of string, end of loop */
5843 *line = 0;
5844 break;
5845 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005846 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005848 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005849 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005850 line++;
5851 args[++arg] = line;
5852 }
5853 else {
5854 line++;
5855 }
5856 }
5857
5858 /* empty line */
5859 if (!**args)
5860 continue;
5861
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005862 if (*line) {
5863 /* we had to stop due to too many args.
5864 * Let's terminate the string, print the offending part then cut the
5865 * last arg.
5866 */
5867 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5868 line++;
5869 *line = '\0';
5870
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005871 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005872 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 args[arg] = line;
5875 }
5876
Willy Tarreau540abe42007-05-02 20:50:16 +02005877 /* zero out remaining args and ensure that at least one entry
5878 * is zeroed out.
5879 */
5880 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 args[arg] = line;
5882 }
5883
Willy Tarreau3842f002009-06-14 11:39:52 +02005884 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005885 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005886 char *tmp;
5887
Willy Tarreau3842f002009-06-14 11:39:52 +02005888 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005889 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005890 for (arg=0; *args[arg+1]; arg++)
5891 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005892 *tmp = '\0'; // fix the next arg to \0
5893 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005894 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005895 else if (!strcmp(args[0], "default")) {
5896 kwm = KWM_DEF;
5897 for (arg=0; *args[arg+1]; arg++)
5898 args[arg] = args[arg+1]; // shift args after inversion
5899 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005900
William Lallemand0f99e342011-10-12 17:50:54 +02005901 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5902 strcmp(args[0], "log") != 0) {
5903 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005904 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005905 }
5906
Willy Tarreau977b8e42006-12-29 14:19:17 +01005907 if (!strcmp(args[0], "listen") ||
5908 !strcmp(args[0], "frontend") ||
5909 !strcmp(args[0], "backend") ||
5910 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005911 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005913 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005914 cursection = strdup(args[0]);
5915 }
5916 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005918 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005919 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005920 }
5921 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005922 confsect = CFG_USERLIST;
5923 free(cursection);
5924 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005925 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005926 else if (!strcmp(args[0], "peers")) {
5927 confsect = CFG_PEERS;
5928 free(cursection);
5929 cursection = strdup(args[0]);
5930 }
5931
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932 /* else it's a section keyword */
5933
5934 switch (confsect) {
5935 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005936 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 break;
5938 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005939 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005941 case CFG_USERLIST:
5942 err_code |= cfg_parse_users(file, linenum, args, kwm);
5943 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005944 case CFG_PEERS:
5945 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5946 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005948 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005951
5952 if (err_code & ERR_ABORT)
5953 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005955 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005956 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005958 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005959}
5960
Willy Tarreaubb925012009-07-23 13:36:36 +02005961/*
5962 * Returns the error code, 0 if OK, or any combination of :
5963 * - ERR_ABORT: must abort ASAP
5964 * - ERR_FATAL: we can continue parsing but not start the service
5965 * - ERR_WARN: a warning has been emitted
5966 * - ERR_ALERT: an alert has been emitted
5967 * Only the two first ones can stop processing, the two others are just
5968 * indicators.
5969 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005970int check_config_validity()
5971{
5972 int cfgerr = 0;
5973 struct proxy *curproxy = NULL;
5974 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005975 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005976 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005977 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005978 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005980 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 /*
5982 * Now, check for the integrity of all that we have collected.
5983 */
5984
5985 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005986 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987
Willy Tarreau193b8c62012-11-22 00:17:38 +01005988 if (!global.tune.max_http_hdr)
5989 global.tune.max_http_hdr = MAX_HTTP_HDR;
5990
5991 if (!global.tune.cookie_len)
5992 global.tune.cookie_len = CAPTURE_LEN;
5993
5994 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5995
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005996 /* first, we will invert the proxy list order */
5997 curproxy = NULL;
5998 while (proxy) {
5999 struct proxy *next;
6000
6001 next = proxy->next;
6002 proxy->next = curproxy;
6003 curproxy = proxy;
6004 if (!next)
6005 break;
6006 proxy = next;
6007 }
6008
Willy Tarreaubaaee002006-06-26 02:48:02 +02006009 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006010 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006011 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006012 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006013 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006014 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006015 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006016 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006017
Willy Tarreau050536d2012-10-04 08:47:34 +02006018 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006019 /* proxy ID not set, use automatic numbering with first
6020 * spare entry starting with next_pxid.
6021 */
6022 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6023 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6024 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006025 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006026 next_pxid++;
6027
Willy Tarreau55ea7572007-06-17 19:56:27 +02006028
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006030 /* ensure we don't keep listeners uselessly bound */
6031 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006032 curproxy = curproxy->next;
6033 continue;
6034 }
6035
Willy Tarreau16a21472012-11-19 12:39:59 +01006036 /* number of processes this proxy is bound to */
6037 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6038
Willy Tarreauff01a212009-03-15 13:46:16 +01006039 switch (curproxy->mode) {
6040 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006041 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006042 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006043 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6044 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006045 cfgerr++;
6046 }
6047
6048 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006049 Warning("config : servers will be ignored for %s '%s'.\n",
6050 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006051 break;
6052
6053 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006054 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006055 break;
6056
6057 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006058 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006059 break;
6060 }
6061
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006062 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006063 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006064 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006065 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6066 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006067 cfgerr++;
6068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006070 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006071 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6072 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006073 cfgerr++;
6074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006076 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006077 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6078 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006079 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006080 }
6081 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006082 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006083 /* If no LB algo is set in a backend, and we're not in
6084 * transparent mode, dispatch mode nor proxy mode, we
6085 * want to use balance roundrobin by default.
6086 */
6087 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6088 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089 }
6090 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006091
Willy Tarreau1620ec32011-08-06 17:05:02 +02006092 if (curproxy->options & PR_O_DISPATCH)
6093 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6094 else if (curproxy->options & PR_O_HTTP_PROXY)
6095 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6096 else if (curproxy->options & PR_O_TRANSP)
6097 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006098
Willy Tarreau1620ec32011-08-06 17:05:02 +02006099 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6100 if (curproxy->options & PR_O_DISABLE404) {
6101 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6102 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6103 err_code |= ERR_WARN;
6104 curproxy->options &= ~PR_O_DISABLE404;
6105 }
6106 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6107 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6108 "send-state", proxy_type_str(curproxy), curproxy->id);
6109 err_code |= ERR_WARN;
6110 curproxy->options &= ~PR_O2_CHK_SNDST;
6111 }
Willy Tarreauef781042010-01-27 11:53:01 +01006112 }
6113
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006114 /* if a default backend was specified, let's find it */
6115 if (curproxy->defbe.name) {
6116 struct proxy *target;
6117
Alex Williams96532db2009-11-01 21:27:13 -05006118 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006119 if (!target) {
6120 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6121 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006122 cfgerr++;
6123 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006124 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6125 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006126 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006127 } else {
6128 free(curproxy->defbe.name);
6129 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006130 /* we force the backend to be present on at least all of
6131 * the frontend's processes.
6132 */
6133 target->bind_proc = curproxy->bind_proc ?
6134 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006135
6136 /* Emit a warning if this proxy also has some servers */
6137 if (curproxy->srv) {
6138 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6139 curproxy->id);
6140 err_code |= ERR_WARN;
6141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 }
6143 }
6144
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006145 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006146 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6147 /* map jump target for ACT_SETBE in req_rep chain */
6148 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006149 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006150 struct proxy *target;
6151
Willy Tarreaua496b602006-12-17 23:15:24 +01006152 if (exp->action != ACT_SETBE)
6153 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006154
Alex Williams96532db2009-11-01 21:27:13 -05006155 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006156 if (!target) {
6157 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6158 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006159 cfgerr++;
6160 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006161 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6162 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006163 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006164 } else {
6165 free((void *)exp->replace);
6166 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006167 /* we force the backend to be present on at least all of
6168 * the frontend's processes.
6169 */
6170 target->bind_proc = curproxy->bind_proc ?
6171 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006172 }
6173 }
6174 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006175
6176 /* find the target proxy for 'use_backend' rules */
6177 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006178 struct proxy *target;
6179
Alex Williams96532db2009-11-01 21:27:13 -05006180 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006181
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006182 if (!target) {
6183 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6184 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006185 cfgerr++;
6186 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006187 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6188 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006189 cfgerr++;
6190 } else {
6191 free((void *)rule->be.name);
6192 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006193 /* we force the backend to be present on at least all of
6194 * the frontend's processes.
6195 */
6196 target->bind_proc = curproxy->bind_proc ?
6197 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006198 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006199 }
6200
6201 /* find the target proxy for 'use_backend' rules */
6202 list_for_each_entry(srule, &curproxy->server_rules, list) {
6203 struct server *target = findserver(curproxy, srule->srv.name);
6204
6205 if (!target) {
6206 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6207 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6208 cfgerr++;
6209 continue;
6210 }
6211 free((void *)srule->srv.name);
6212 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006213 }
6214
Emeric Brunb982a3d2010-01-04 15:45:53 +01006215 /* find the target table for 'stick' rules */
6216 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6217 struct proxy *target;
6218
Emeric Brun1d33b292010-01-04 15:47:17 +01006219 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6220 if (mrule->flags & STK_IS_STORE)
6221 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6222
Emeric Brunb982a3d2010-01-04 15:45:53 +01006223 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006224 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006225 else
6226 target = curproxy;
6227
6228 if (!target) {
6229 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6230 curproxy->id, mrule->table.name);
6231 cfgerr++;
6232 }
6233 else if (target->table.size == 0) {
6234 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6235 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6236 cfgerr++;
6237 }
Willy Tarreau12785782012-04-27 21:37:17 +02006238 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6239 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006240 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6241 cfgerr++;
6242 }
6243 else {
6244 free((void *)mrule->table.name);
6245 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006246 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006247 }
6248 }
6249
6250 /* find the target table for 'store response' rules */
6251 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6252 struct proxy *target;
6253
Emeric Brun1d33b292010-01-04 15:47:17 +01006254 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6255
Emeric Brunb982a3d2010-01-04 15:45:53 +01006256 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006257 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006258 else
6259 target = curproxy;
6260
6261 if (!target) {
6262 Alert("Proxy '%s': unable to find store table '%s'.\n",
6263 curproxy->id, mrule->table.name);
6264 cfgerr++;
6265 }
6266 else if (target->table.size == 0) {
6267 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6268 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6269 cfgerr++;
6270 }
Willy Tarreau12785782012-04-27 21:37:17 +02006271 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6272 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006273 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6274 cfgerr++;
6275 }
6276 else {
6277 free((void *)mrule->table.name);
6278 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006279 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006280 }
6281 }
6282
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006283 /* find the target table for 'tcp-request' layer 4 rules */
6284 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6285 struct proxy *target;
6286
Willy Tarreau56123282010-08-06 19:06:56 +02006287 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006288 continue;
6289
6290 if (trule->act_prm.trk_ctr.table.n)
6291 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6292 else
6293 target = curproxy;
6294
6295 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006296 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6297 curproxy->id, trule->act_prm.trk_ctr.table.n,
6298 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006299 cfgerr++;
6300 }
6301 else if (target->table.size == 0) {
6302 Alert("Proxy '%s': table '%s' used but not configured.\n",
6303 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6304 cfgerr++;
6305 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006306 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6307 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6308 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6309 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6310 cfgerr++;
6311 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006312 else {
6313 free(trule->act_prm.trk_ctr.table.n);
6314 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006315 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006316 * to pass a list of counters to track and allocate them right here using
6317 * stktable_alloc_data_type().
6318 */
6319 }
6320 }
6321
Willy Tarreaud1f96522010-08-03 19:34:32 +02006322 /* find the target table for 'tcp-request' layer 6 rules */
6323 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6324 struct proxy *target;
6325
Willy Tarreau56123282010-08-06 19:06:56 +02006326 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006327 continue;
6328
6329 if (trule->act_prm.trk_ctr.table.n)
6330 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6331 else
6332 target = curproxy;
6333
6334 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006335 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6336 curproxy->id, trule->act_prm.trk_ctr.table.n,
6337 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006338 cfgerr++;
6339 }
6340 else if (target->table.size == 0) {
6341 Alert("Proxy '%s': table '%s' used but not configured.\n",
6342 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6343 cfgerr++;
6344 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006345 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6346 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6347 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6348 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6349 cfgerr++;
6350 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006351 else {
6352 free(trule->act_prm.trk_ctr.table.n);
6353 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006354 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006355 * to pass a list of counters to track and allocate them right here using
6356 * stktable_alloc_data_type().
6357 */
6358 }
6359 }
6360
Emeric Brun32da3c42010-09-23 18:39:19 +02006361 if (curproxy->table.peers.name) {
6362 struct peers *curpeers = peers;
6363
6364 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6365 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6366 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006367 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006368 break;
6369 }
6370 }
6371
6372 if (!curpeers) {
6373 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6374 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006375 free((void *)curproxy->table.peers.name);
6376 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006377 cfgerr++;
6378 }
6379 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006380 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6381 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006382 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006383 cfgerr++;
6384 }
6385 }
6386
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006387 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006388 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6390 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6391 "proxy", curproxy->id);
6392 cfgerr++;
6393 goto out_uri_auth_compat;
6394 }
6395
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006396 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006397 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006398 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006399 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006400
Willy Tarreau95fa4692010-02-01 13:05:50 +01006401 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6402 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006403
6404 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006405 uri_auth_compat_req[i++] = "realm";
6406 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6407 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006408
Willy Tarreau95fa4692010-02-01 13:05:50 +01006409 uri_auth_compat_req[i++] = "unless";
6410 uri_auth_compat_req[i++] = "{";
6411 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6412 uri_auth_compat_req[i++] = "}";
6413 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006414
Willy Tarreauff011f22011-01-06 17:51:27 +01006415 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6416 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006417 cfgerr++;
6418 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006419 }
6420
Willy Tarreauff011f22011-01-06 17:51:27 +01006421 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006422
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006423 if (curproxy->uri_auth->auth_realm) {
6424 free(curproxy->uri_auth->auth_realm);
6425 curproxy->uri_auth->auth_realm = NULL;
6426 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006427
6428 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006429 }
6430out_uri_auth_compat:
6431
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006432 cfgerr += acl_find_targets(curproxy);
6433
Willy Tarreau2738a142006-07-08 17:28:09 +02006434 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006435 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006436 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006437 (!curproxy->timeout.connect ||
6438 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006439 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006440 " | While not properly invalid, you will certainly encounter various problems\n"
6441 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006442 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006443 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006444 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006445 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006446
Willy Tarreau1fa31262007-12-03 00:36:16 +01006447 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6448 * We must still support older configurations, so let's find out whether those
6449 * parameters have been set or must be copied from contimeouts.
6450 */
6451 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006452 if (!curproxy->timeout.tarpit ||
6453 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006454 /* tarpit timeout not set. We search in the following order:
6455 * default.tarpit, curr.connect, default.connect.
6456 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006457 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006458 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006459 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006460 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006461 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006462 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006463 }
6464 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006465 (!curproxy->timeout.queue ||
6466 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006467 /* queue timeout not set. We search in the following order:
6468 * default.queue, curr.connect, default.connect.
6469 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006470 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006471 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006472 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006473 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006474 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006475 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006476 }
6477 }
6478
Willy Tarreau1620ec32011-08-06 17:05:02 +02006479 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006480 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6481 curproxy->check_req = (char *)malloc(curproxy->check_len);
6482 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006483 }
6484
Willy Tarreau193b8c62012-11-22 00:17:38 +01006485 /* ensure that cookie capture length is not too large */
6486 if (curproxy->capture_len >= global.tune.cookie_len) {
6487 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6488 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6489 err_code |= ERR_WARN;
6490 curproxy->capture_len = global.tune.cookie_len - 1;
6491 }
6492
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006493 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006494 if (curproxy->nb_req_cap) {
6495 if (curproxy->mode == PR_MODE_HTTP) {
6496 curproxy->req_cap_pool = create_pool("ptrcap",
6497 curproxy->nb_req_cap * sizeof(char *),
6498 MEM_F_SHARED);
6499 } else {
6500 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6501 proxy_type_str(curproxy), curproxy->id);
6502 err_code |= ERR_WARN;
6503 curproxy->to_log &= ~LW_REQHDR;
6504 curproxy->nb_req_cap = 0;
6505 }
6506 }
6507
6508 if (curproxy->nb_rsp_cap) {
6509 if (curproxy->mode == PR_MODE_HTTP) {
6510 curproxy->rsp_cap_pool = create_pool("ptrcap",
6511 curproxy->nb_rsp_cap * sizeof(char *),
6512 MEM_F_SHARED);
6513 } else {
6514 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6515 proxy_type_str(curproxy), curproxy->id);
6516 err_code |= ERR_WARN;
6517 curproxy->to_log &= ~LW_REQHDR;
6518 curproxy->nb_rsp_cap = 0;
6519 }
6520 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006521
Willy Tarreau196729e2012-05-31 19:30:26 +02006522 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006523 if (!(curproxy->cap & PR_CAP_FE)) {
6524 if (curproxy->logformat_string != default_http_log_format &&
6525 curproxy->logformat_string != default_tcp_log_format &&
6526 curproxy->logformat_string != clf_http_log_format)
6527 free(curproxy->logformat_string);
6528 curproxy->logformat_string = NULL;
6529 }
6530
Willy Tarreau196729e2012-05-31 19:30:26 +02006531 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006532 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006533
6534 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006535 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006536
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 /* first, we will invert the servers list order */
6538 newsrv = NULL;
6539 while (curproxy->srv) {
6540 struct server *next;
6541
6542 next = curproxy->srv->next;
6543 curproxy->srv->next = newsrv;
6544 newsrv = curproxy->srv;
6545 if (!next)
6546 break;
6547 curproxy->srv = next;
6548 }
6549
Willy Tarreaudd701652010-05-25 23:03:02 +02006550 /* assign automatic UIDs to servers which don't have one yet */
6551 next_id = 1;
6552 newsrv = curproxy->srv;
6553 while (newsrv != NULL) {
6554 if (!newsrv->puid) {
6555 /* server ID not set, use automatic numbering with first
6556 * spare entry starting with next_svid.
6557 */
6558 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6559 newsrv->conf.id.key = newsrv->puid = next_id;
6560 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6561 }
6562 next_id++;
6563 newsrv = newsrv->next;
6564 }
6565
Willy Tarreau20697042007-11-15 23:26:18 +01006566 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006567 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568
Willy Tarreau62c3be22012-01-20 13:12:32 +01006569 /*
6570 * If this server supports a maxconn parameter, it needs a dedicated
6571 * tasks to fill the emptied slots when a connection leaves.
6572 * Also, resolve deferred tracking dependency if needed.
6573 */
6574 newsrv = curproxy->srv;
6575 while (newsrv != NULL) {
6576 if (newsrv->minconn > newsrv->maxconn) {
6577 /* Only 'minconn' was specified, or it was higher than or equal
6578 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6579 * this will avoid further useless expensive computations.
6580 */
6581 newsrv->maxconn = newsrv->minconn;
6582 } else if (newsrv->maxconn && !newsrv->minconn) {
6583 /* minconn was not specified, so we set it to maxconn */
6584 newsrv->minconn = newsrv->maxconn;
6585 }
6586
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006587#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006588 if (newsrv->use_ssl || newsrv->check.use_ssl)
6589 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006590#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006591
Willy Tarreau62c3be22012-01-20 13:12:32 +01006592 if (newsrv->trackit) {
6593 struct proxy *px;
6594 struct server *srv;
6595 char *pname, *sname;
6596
6597 pname = newsrv->trackit;
6598 sname = strrchr(pname, '/');
6599
6600 if (sname)
6601 *sname++ = '\0';
6602 else {
6603 sname = pname;
6604 pname = NULL;
6605 }
6606
6607 if (pname) {
6608 px = findproxy(pname, PR_CAP_BE);
6609 if (!px) {
6610 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6611 proxy_type_str(curproxy), curproxy->id,
6612 newsrv->id, pname);
6613 cfgerr++;
6614 goto next_srv;
6615 }
6616 } else
6617 px = curproxy;
6618
6619 srv = findserver(px, sname);
6620 if (!srv) {
6621 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6622 proxy_type_str(curproxy), curproxy->id,
6623 newsrv->id, sname);
6624 cfgerr++;
6625 goto next_srv;
6626 }
6627
6628 if (!(srv->state & SRV_CHECKED)) {
6629 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6630 "tracking as it does not have checks enabled.\n",
6631 proxy_type_str(curproxy), curproxy->id,
6632 newsrv->id, px->id, srv->id);
6633 cfgerr++;
6634 goto next_srv;
6635 }
6636
6637 if (curproxy != px &&
6638 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6639 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6640 "tracking: disable-on-404 option inconsistency.\n",
6641 proxy_type_str(curproxy), curproxy->id,
6642 newsrv->id, px->id, srv->id);
6643 cfgerr++;
6644 goto next_srv;
6645 }
6646
6647 /* if the other server is forced disabled, we have to do the same here */
6648 if (srv->state & SRV_MAINTAIN) {
6649 newsrv->state |= SRV_MAINTAIN;
6650 newsrv->state &= ~SRV_RUNNING;
6651 newsrv->health = 0;
6652 }
6653
6654 newsrv->track = srv;
6655 newsrv->tracknext = srv->tracknext;
6656 srv->tracknext = newsrv;
6657
6658 free(newsrv->trackit);
6659 newsrv->trackit = NULL;
6660 }
6661 next_srv:
6662 newsrv = newsrv->next;
6663 }
6664
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006665 /* We have to initialize the server lookup mechanism depending
6666 * on what LB algorithm was choosen.
6667 */
6668
6669 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6670 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6671 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006672 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6673 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6674 init_server_map(curproxy);
6675 } else {
6676 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6677 fwrr_init_server_groups(curproxy);
6678 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006679 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006680
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006681 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006682 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6683 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6684 fwlc_init_server_tree(curproxy);
6685 } else {
6686 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6687 fas_init_server_tree(curproxy);
6688 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006689 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006690
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006691 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006692 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6693 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6694 chash_init_server_tree(curproxy);
6695 } else {
6696 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6697 init_server_map(curproxy);
6698 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006699 break;
6700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006701
6702 if (curproxy->options & PR_O_LOGASAP)
6703 curproxy->to_log &= ~LW_BYTES;
6704
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006705 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006706 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006707 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6708 proxy_type_str(curproxy), curproxy->id);
6709 err_code |= ERR_WARN;
6710 }
6711
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006712 if (curproxy->mode != PR_MODE_HTTP) {
6713 int optnum;
6714
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006715 if (curproxy->uri_auth) {
6716 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6717 proxy_type_str(curproxy), curproxy->id);
6718 err_code |= ERR_WARN;
6719 curproxy->uri_auth = NULL;
6720 }
6721
Willy Tarreau87cf5142011-08-19 22:57:24 +02006722 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006723 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6724 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6725 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006726 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006727 }
6728
6729 if (curproxy->options & PR_O_ORGTO) {
6730 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6731 "originalto", proxy_type_str(curproxy), curproxy->id);
6732 err_code |= ERR_WARN;
6733 curproxy->options &= ~PR_O_ORGTO;
6734 }
6735
6736 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6737 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6738 (curproxy->cap & cfg_opts[optnum].cap) &&
6739 (curproxy->options & cfg_opts[optnum].val)) {
6740 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6741 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6742 err_code |= ERR_WARN;
6743 curproxy->options &= ~cfg_opts[optnum].val;
6744 }
6745 }
6746
6747 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6748 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6749 (curproxy->cap & cfg_opts2[optnum].cap) &&
6750 (curproxy->options2 & cfg_opts2[optnum].val)) {
6751 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6752 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6753 err_code |= ERR_WARN;
6754 curproxy->options2 &= ~cfg_opts2[optnum].val;
6755 }
6756 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006757
Willy Tarreauefa5f512010-03-30 20:13:29 +02006758#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006759 if (curproxy->conn_src.bind_hdr_occ) {
6760 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006761 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006762 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006763 err_code |= ERR_WARN;
6764 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006765#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006766 }
6767
Willy Tarreaubaaee002006-06-26 02:48:02 +02006768 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006769 * ensure that we're not cross-dressing a TCP server into HTTP.
6770 */
6771 newsrv = curproxy->srv;
6772 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006773 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006774 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6775 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006776 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006777 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006778
Willy Tarreau0cec3312011-10-31 13:49:26 +01006779 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6780 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6781 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6782 err_code |= ERR_WARN;
6783 }
6784
Willy Tarreauefa5f512010-03-30 20:13:29 +02006785#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006786 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6787 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006788 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 +01006789 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006790 err_code |= ERR_WARN;
6791 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006792#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006793 newsrv = newsrv->next;
6794 }
6795
Willy Tarreauc1a21672009-08-16 22:37:44 +02006796 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006797 if (!curproxy->accept)
6798 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006799
Willy Tarreauc1a21672009-08-16 22:37:44 +02006800 if (curproxy->tcp_req.inspect_delay ||
6801 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006802 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006803
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006804 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006805 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006806 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006807 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006808
6809 /* both TCP and HTTP must check switching rules */
6810 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6811 }
6812
6813 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006814 if (curproxy->tcp_req.inspect_delay ||
6815 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6816 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6817
Emeric Brun97679e72010-09-23 17:56:44 +02006818 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6819 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6820
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006821 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006822 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006823 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006824 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006825
6826 /* If the backend does requires RDP cookie persistence, we have to
6827 * enable the corresponding analyser.
6828 */
6829 if (curproxy->options2 & PR_O2_RDPC_PRST)
6830 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6831 }
6832
Emeric Brunc52962f2012-11-15 18:28:02 +01006833#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006834 /* Configure SSL for each bind line.
6835 * Note: if configuration fails at some point, the ->ctx member
6836 * remains NULL so that listeners can later detach.
6837 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006838 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006839 if (!bind_conf->is_ssl) {
6840 if (bind_conf->default_ctx) {
6841 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6842 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6843 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006844 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006845 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006846 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006847 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006848 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006849 cfgerr++;
6850 continue;
6851 }
6852
Emeric Brun4b3091e2012-09-24 15:48:52 +02006853 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006854 Alert("Unable to allocate SSL session cache.\n");
6855 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006856 continue;
6857 }
6858
Emeric Brunfc0421f2012-09-07 17:30:07 +02006859 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006860 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006861 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006862#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006863
Willy Tarreaue6b98942007-10-29 01:09:36 +01006864 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006865 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006866 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006867 if (!listener->luid) {
6868 /* listener ID not set, use automatic numbering with first
6869 * spare entry starting with next_luid.
6870 */
6871 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6872 listener->conf.id.key = listener->luid = next_id;
6873 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006874 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006875 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006876
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006877 /* enable separate counters */
6878 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6879 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006880 if (!listener->name)
6881 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006882 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006883
Willy Tarreaue6b98942007-10-29 01:09:36 +01006884 if (curproxy->options & PR_O_TCP_NOLING)
6885 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006886 if (!listener->maxconn)
6887 listener->maxconn = curproxy->maxconn;
6888 if (!listener->backlog)
6889 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006890 if (!listener->maxaccept)
6891 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6892
6893 /* we want to have an optimal behaviour on single process mode to
6894 * maximize the work at once, but in multi-process we want to keep
6895 * some fairness between processes, so we target half of the max
6896 * number of events to be balanced over all the processes the proxy
6897 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6898 * used to disable the limit.
6899 */
6900 if (listener->maxaccept > 0) {
6901 if (nbproc > 1)
6902 listener->maxaccept = (listener->maxaccept + 1) / 2;
6903 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6904 }
6905
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006906 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006907 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006908 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006909 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006910
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006911 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6912 listener->options |= LI_O_TCP_RULES;
6913
Willy Tarreaude3041d2010-05-31 10:56:17 +02006914 if (curproxy->mon_mask.s_addr)
6915 listener->options |= LI_O_CHK_MONNET;
6916
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006917 /* smart accept mode is automatic in HTTP mode */
6918 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006919 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006920 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6921 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006922 }
6923
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006924 /* Release unused SSL configs */
6925 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6926 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006927 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006928#ifdef USE_OPENSSL
6929 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006930 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006931 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006932 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006933 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006934#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006935 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006936
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006937 /* Check multi-process mode compatibility for the current proxy */
6938 if (global.nbproc > 1) {
6939 int nbproc = 0;
6940 if (curproxy->bind_proc) {
6941 int proc;
6942 for (proc = 0; proc < global.nbproc; proc++) {
6943 if (curproxy->bind_proc & (1 << proc)) {
6944 nbproc++;
6945 }
6946 }
6947 } else {
6948 nbproc = global.nbproc;
6949 }
6950 if (curproxy->table.peers.name) {
6951 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6952 curproxy->id);
6953 cfgerr++;
6954 }
6955 if (nbproc > 1) {
6956 if (curproxy->uri_auth) {
6957 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6958 curproxy->id);
6959 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6960 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6961 curproxy->id);
6962 }
6963 }
6964 if (curproxy->appsession_name) {
6965 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6966 curproxy->id);
6967 }
6968 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6969 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6970 curproxy->id);
6971 }
6972 }
6973 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006974
6975 /* create the task associated with the proxy */
6976 curproxy->task = task_new();
6977 if (curproxy->task) {
6978 curproxy->task->context = curproxy;
6979 curproxy->task->process = manage_proxy;
6980 /* no need to queue, it will be done automatically if some
6981 * listener gets limited.
6982 */
6983 curproxy->task->expire = TICK_ETERNITY;
6984 } else {
6985 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6986 curproxy->id);
6987 cfgerr++;
6988 }
6989
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990 curproxy = curproxy->next;
6991 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006992
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006993 /* Check multi-process mode compatibility */
6994 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006995 if (global.stats_fe && !global.stats_fe->bind_proc) {
6996 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 +01006997 }
6998 }
6999
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007000 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7001 struct auth_users *curuser;
7002 int g;
7003
7004 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7005 unsigned int group_mask = 0;
7006 char *group = NULL;
7007
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007008 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007009 continue;
7010
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007011 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007012
7013 for (g = 0; g < curuserlist->grpcnt; g++)
7014 if (!strcmp(curuserlist->groups[g], group))
7015 break;
7016
7017 if (g == curuserlist->grpcnt) {
7018 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7019 curuserlist->name, group, curuser->user);
7020 err_code |= ERR_ALERT | ERR_FATAL;
7021 goto out;
7022 }
7023
7024 group_mask |= (1 << g);
7025 }
7026
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007027 free(curuser->u.groups);
7028 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007029 }
7030
7031 for (g = 0; g < curuserlist->grpcnt; g++) {
7032 char *user = NULL;
7033
7034 if (!curuserlist->groupusers[g])
7035 continue;
7036
7037 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7038 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7039 if (!strcmp(curuser->user, user))
7040 break;
7041
7042 if (!curuser) {
7043 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7044 curuserlist->name, user, curuserlist->groups[g]);
7045 err_code |= ERR_ALERT | ERR_FATAL;
7046 goto out;
7047 }
7048
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007049 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007050 }
7051
7052 free(curuserlist->groupusers[g]);
7053 }
7054
7055 free(curuserlist->groupusers);
7056
7057#ifdef DEBUG_AUTH
7058 for (g = 0; g < curuserlist->grpcnt; g++) {
7059 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7060
7061 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007062 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007063 fprintf(stderr, " %s", curuser->user);
7064 }
7065
7066 fprintf(stderr, "\n");
7067 }
7068#endif
7069
Willy Tarreaufbb78422011-06-05 15:38:35 +02007070 }
7071
7072 /* automatically compute fullconn if not set. We must not do it in the
7073 * loop above because cross-references are not yet fully resolved.
7074 */
7075 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7076 /* If <fullconn> is not set, let's set it to 10% of the sum of
7077 * the possible incoming frontend's maxconns.
7078 */
7079 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7080 struct proxy *fe;
7081 int total = 0;
7082
7083 /* sum up the number of maxconns of frontends which
7084 * reference this backend at least once or which are
7085 * the same one ('listen').
7086 */
7087 for (fe = proxy; fe; fe = fe->next) {
7088 struct switching_rule *rule;
7089 struct hdr_exp *exp;
7090 int found = 0;
7091
7092 if (!(fe->cap & PR_CAP_FE))
7093 continue;
7094
7095 if (fe == curproxy) /* we're on a "listen" instance */
7096 found = 1;
7097
7098 if (fe->defbe.be == curproxy) /* "default_backend" */
7099 found = 1;
7100
7101 /* check if a "use_backend" rule matches */
7102 if (!found) {
7103 list_for_each_entry(rule, &fe->switching_rules, list) {
7104 if (rule->be.backend == curproxy) {
7105 found = 1;
7106 break;
7107 }
7108 }
7109 }
7110
7111 /* check if a "reqsetbe" rule matches */
7112 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7113 if (exp->action == ACT_SETBE &&
7114 (struct proxy *)exp->replace == curproxy) {
7115 found = 1;
7116 break;
7117 }
7118 }
7119
7120 /* now we've checked all possible ways to reference a backend
7121 * from a frontend.
7122 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007123 if (!found)
7124 continue;
7125 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007126 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007127 /* we have the sum of the maxconns in <total>. We only
7128 * keep 10% of that sum to set the default fullconn, with
7129 * a hard minimum of 1 (to avoid a divide by zero).
7130 */
7131 curproxy->fullconn = (total + 9) / 10;
7132 if (!curproxy->fullconn)
7133 curproxy->fullconn = 1;
7134 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007135 }
7136
Willy Tarreau056f5682010-06-06 15:51:11 +02007137 /* initialize stick-tables on backend capable proxies. This must not
7138 * be done earlier because the data size may be discovered while parsing
7139 * other proxies.
7140 */
7141 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007142 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007143
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007144 /*
7145 * Recount currently required checks.
7146 */
7147
7148 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7149 int optnum;
7150
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007151 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7152 if (curproxy->options & cfg_opts[optnum].val)
7153 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007154
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007155 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7156 if (curproxy->options2 & cfg_opts2[optnum].val)
7157 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007158 }
7159
Willy Tarreau122541c2011-09-07 21:24:49 +02007160 if (peers) {
7161 struct peers *curpeers = peers, **last;
7162 struct peer *p, *pb;
7163
7164 /* Remove all peers sections which don't have a valid listener.
7165 * This can happen when a peers section is never referenced and
7166 * does not contain a local peer.
7167 */
7168 last = &peers;
7169 while (*last) {
7170 curpeers = *last;
7171 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007172 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007173 last = &curpeers->next;
7174 continue;
7175 }
7176
7177 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7178 curpeers->id, localpeer);
7179
7180 p = curpeers->remote;
7181 while (p) {
7182 pb = p->next;
7183 free(p->id);
7184 free(p);
7185 p = pb;
7186 }
7187
7188 /* Destroy and unlink this curpeers section.
7189 * Note: curpeers is backed up into *last.
7190 */
7191 free(curpeers->id);
7192 curpeers = curpeers->next;
7193 free(*last);
7194 *last = curpeers;
7195 }
7196 }
7197
Willy Tarreau34eb6712011-10-24 18:15:04 +02007198 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007199 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007200 MEM_F_SHARED);
7201
Willy Tarreaubb925012009-07-23 13:36:36 +02007202 if (cfgerr > 0)
7203 err_code |= ERR_ALERT | ERR_FATAL;
7204 out:
7205 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007206}
7207
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007208/*
7209 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7210 * parsing sessions.
7211 */
7212void cfg_register_keywords(struct cfg_kw_list *kwl)
7213{
7214 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7215}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007216
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007217/*
7218 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7219 */
7220void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7221{
7222 LIST_DEL(&kwl->list);
7223 LIST_INIT(&kwl->list);
7224}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007225
7226/*
7227 * Local variables:
7228 * c-indent-level: 8
7229 * c-basic-offset: 8
7230 * End:
7231 */