blob: 60270da7c32932cc482af764e1d0456636b2665a [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 Tarreaud5191e72010-02-09 20:50:45 +01004465
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004467 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4468 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004472 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud393a622013-03-04 18:22:00 +01004473 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004474 if (!sk) {
4475 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004479 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004480
4481 if (port_low != port_high) {
4482 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004483
4484 if (!port_low || !port_high) {
4485 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4486 file, linenum, args[cur_arg], args[cur_arg + 1]);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
4490
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004491 if (port_low <= 0 || port_low > 65535 ||
4492 port_high <= 0 || port_high > 65535 ||
4493 port_low > port_high) {
4494 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4495 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004498 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004499 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4500 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4501 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004502 }
4503
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505 while (*(args[cur_arg])) {
4506 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004507#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4508#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004509 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004510 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4511 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004514 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004515#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004516 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004517 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004518 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004521 }
4522 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004523 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4524 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004526 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4527 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004528 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4529 char *name, *end;
4530
4531 name = args[cur_arg+1] + 7;
4532 while (isspace(*name))
4533 name++;
4534
4535 end = name;
4536 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4537 end++;
4538
Willy Tarreauef9a3602012-12-08 22:29:20 +01004539 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4540 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4541 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4542 newsrv->conn_src.bind_hdr_len = end - name;
4543 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4544 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4545 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004546
4547 /* now look for an occurrence number */
4548 while (isspace(*end))
4549 end++;
4550 if (*end == ',') {
4551 end++;
4552 name = end;
4553 if (*end == '-')
4554 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004555 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004556 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004557 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004558 }
4559
Willy Tarreauef9a3602012-12-08 22:29:20 +01004560 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004561 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4562 " occurrences values smaller than %d.\n",
4563 file, linenum, MAX_HDR_HISTORY);
4564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
4566 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004567 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004568 struct sockaddr_storage *sk;
4569 int port1, port2;
4570
Willy Tarreaud393a622013-03-04 18:22:00 +01004571 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004572 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004573 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4574 file, linenum, args[cur_arg], args[cur_arg + 1]);
4575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
4577 }
4578 if (port1 != port2) {
4579 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4580 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
4583 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004584 newsrv->conn_src.tproxy_addr = *sk;
4585 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004586 }
4587 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004588#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004589 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004590#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004591 cur_arg += 2;
4592 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004593#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004594 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004595 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004598#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4599 } /* "usesrc" */
4600
4601 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4602#ifdef SO_BINDTODEVICE
4603 if (!*args[cur_arg + 1]) {
4604 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004608 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004609 free(newsrv->conn_src.iface_name);
4610 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4611 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004612 global.last_checks |= LSTCHK_NETADM;
4613#else
4614 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4615 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004618#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004619 cur_arg += 2;
4620 continue;
4621 }
4622 /* this keyword in not an option of "source" */
4623 break;
4624 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004626 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004627 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4628 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004632 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004633 static int srv_dumped;
4634 struct srv_kw *kw;
4635 char *err;
4636
4637 kw = srv_find_kw(args[cur_arg]);
4638 if (kw) {
4639 char *err = NULL;
4640 int code;
4641
4642 if (!kw->parse) {
4643 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4644 file, linenum, args[0], args[1], args[cur_arg]);
4645 cur_arg += 1 + kw->skip ;
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649
4650 if (defsrv && !kw->default_ok) {
4651 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4652 file, linenum, args[0], args[1], args[cur_arg]);
4653 cur_arg += 1 + kw->skip ;
4654 err_code |= ERR_ALERT;
4655 continue;
4656 }
4657
4658 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4659 err_code |= code;
4660
4661 if (code) {
4662 if (err && *err) {
4663 indent_msg(&err, 2);
4664 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4665 }
4666 else
4667 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4668 file, linenum, args[0], args[1], args[cur_arg]);
4669 if (code & ERR_FATAL) {
4670 free(err);
4671 cur_arg += 1 + kw->skip;
4672 goto out;
4673 }
4674 }
4675 free(err);
4676 cur_arg += 1 + kw->skip;
4677 continue;
4678 }
4679
4680 err = NULL;
4681 if (!srv_dumped) {
4682 srv_dump_kws(&err);
4683 indent_msg(&err, 4);
4684 srv_dumped = 1;
4685 }
4686
4687 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4688 file, linenum, args[0], args[1], args[cur_arg],
4689 err ? " Registered keywords :" : "", err ? err : "");
4690 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004691
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 }
4695 }
4696
4697 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004698 if (newsrv->trackit) {
4699 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4700 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004703 }
4704
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004705 /* If neither a port nor an addr was specified and no check transport
4706 * layer is forced, then the transport layer used by the checks is the
4707 * same as for the production traffic. Otherwise we use raw_sock by
4708 * default, unless one is specified.
4709 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004710 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004711#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004712 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004713#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004714 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4715 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004716 /* try to get the port from check.addr if check.port not set */
4717 if (!newsrv->check.port)
4718 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004719
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004720 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004721 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004722
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004723 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004724 /* not yet valid, because no port was set on
4725 * the server either. We'll check if we have
4726 * a known port on the first listener.
4727 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004728 struct listener *l;
4729
4730 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004731 newsrv->check.port = get_host_port(&l->addr);
4732 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004733 break;
4734 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004735 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004736 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4738 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004742
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004743 /* Allocate buffer for check requests... */
4744 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004745 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4746 err_code |= ERR_ALERT | ERR_ABORT;
4747 goto out;
4748 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004749 newsrv->check.bi->size = global.tune.chksize;
4750
4751 /* Allocate buffer for check responses... */
4752 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4753 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4754 err_code |= ERR_ALERT | ERR_ABORT;
4755 goto out;
4756 }
4757 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004758
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004759 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004760 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004761 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4762 err_code |= ERR_ALERT | ERR_ABORT;
4763 goto out;
4764 }
4765
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004766 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4767 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 newsrv->state |= SRV_CHECKED;
4769 }
4770
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004771 if (!defsrv) {
4772 if (newsrv->state & SRV_BACKUP)
4773 curproxy->srv_bck++;
4774 else
4775 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004776
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004777 newsrv->prev_state = newsrv->state;
4778 }
William Lallemanda73203e2012-03-12 12:48:57 +01004779 }
4780
4781 else if (strcmp(args[0], "unique-id-format") == 0) {
4782 if (!*(args[1])) {
4783 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
William Lallemand3203ff42012-11-11 17:30:56 +01004787 if (*(args[2])) {
4788 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004792 free(curproxy->uniqueid_format_string);
4793 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004794 }
William Lallemanda73203e2012-03-12 12:48:57 +01004795
4796 else if (strcmp(args[0], "unique-id-header") == 0) {
4797 if (!*(args[1])) {
4798 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
4802 free(curproxy->header_unique_id);
4803 curproxy->header_unique_id = strdup(args[1]);
4804 }
4805
William Lallemand723b73a2012-02-08 16:37:49 +01004806 else if (strcmp(args[0], "log-format") == 0) {
4807 if (!*(args[1])) {
4808 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
William Lallemand3203ff42012-11-11 17:30:56 +01004812 if (*(args[2])) {
4813 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004817
4818 if (curproxy->logformat_string != default_http_log_format &&
4819 curproxy->logformat_string != default_tcp_log_format &&
4820 curproxy->logformat_string != clf_http_log_format)
4821 free(curproxy->logformat_string);
4822 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
William Lallemand723b73a2012-02-08 16:37:49 +01004824
William Lallemand0f99e342011-10-12 17:50:54 +02004825 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4826 /* delete previous herited or defined syslog servers */
4827 struct logsrv *back;
4828
4829 if (*(args[1]) != 0) {
4830 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
4834
William Lallemand723b73a2012-02-08 16:37:49 +01004835 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4836 LIST_DEL(&tmplogsrv->list);
4837 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004838 }
4839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004841 struct logsrv *logsrv;
4842
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004844 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004845 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004846 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004847 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004848 LIST_INIT(&node->list);
4849 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
4852 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004853 struct sockaddr_storage *sk;
4854 int port1, port2;
4855 char *err_msg = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02004856
4857 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858
William Lallemand0f99e342011-10-12 17:50:54 +02004859 logsrv->facility = get_log_facility(args[2]);
4860 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 }
4866
William Lallemand0f99e342011-10-12 17:50:54 +02004867 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004869 logsrv->level = get_log_level(args[3]);
4870 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 }
4876 }
4877
William Lallemand0f99e342011-10-12 17:50:54 +02004878 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004879 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004880 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004881 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004882 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004886 }
4887 }
4888
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004889 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
4890 if (!sk) {
4891 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], err_msg);
4892 err_code |= ERR_ALERT | ERR_FATAL;
4893 free(err_msg);
4894 goto out;
4895 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004896
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004897 logsrv->addr = *sk;
4898 free(err_msg);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004899
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004900 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004901 if (port1 != port2) {
4902 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4903 file, linenum, args[0], args[1]);
4904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
4906 }
4907
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004908 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004909 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
William Lallemand0f99e342011-10-12 17:50:54 +02004911
4912 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 else {
4915 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4916 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
4920 }
4921 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004922 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004923 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004924 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004925
Willy Tarreau977b8e42006-12-29 14:19:17 +01004926 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004928
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004930 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4931 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004932 err_code |= ERR_ALERT | ERR_FATAL;
4933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004935
4936 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004937 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4938 free(curproxy->conn_src.iface_name);
4939 curproxy->conn_src.iface_name = NULL;
4940 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004941
Willy Tarreaud393a622013-03-04 18:22:00 +01004942 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004943 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004944 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4945 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
4948 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004949
4950 if (port1 != port2) {
4951 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4952 file, linenum, args[0], args[1]);
4953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
4955 }
4956
Willy Tarreauef9a3602012-12-08 22:29:20 +01004957 curproxy->conn_src.source_addr = *sk;
4958 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959
4960 cur_arg = 2;
4961 while (*(args[cur_arg])) {
4962 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004963#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4964#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004965 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004966 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4967 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004970 }
4971#endif
4972 if (!*args[cur_arg + 1]) {
4973 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4974 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004977 }
4978
4979 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004980 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4981 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004982 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004983 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4984 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004985 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4986 char *name, *end;
4987
4988 name = args[cur_arg+1] + 7;
4989 while (isspace(*name))
4990 name++;
4991
4992 end = name;
4993 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4994 end++;
4995
Willy Tarreauef9a3602012-12-08 22:29:20 +01004996 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4997 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4998 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4999 curproxy->conn_src.bind_hdr_len = end - name;
5000 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5001 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5002 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005003
5004 /* now look for an occurrence number */
5005 while (isspace(*end))
5006 end++;
5007 if (*end == ',') {
5008 end++;
5009 name = end;
5010 if (*end == '-')
5011 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005012 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005013 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005014 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005015 }
5016
Willy Tarreauef9a3602012-12-08 22:29:20 +01005017 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005018 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5019 " occurrences values smaller than %d.\n",
5020 file, linenum, MAX_HDR_HISTORY);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005024 } else {
Willy Tarreaud393a622013-03-04 18:22:00 +01005025 struct sockaddr_storage *sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005026
Willy Tarreaud5191e72010-02-09 20:50:45 +01005027 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005028 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
5029 file, linenum, args[cur_arg], args[cur_arg + 1]);
5030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
5033 if (port1 != port2) {
5034 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5035 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005039 curproxy->conn_src.tproxy_addr = *sk;
5040 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 }
5042 global.last_checks |= LSTCHK_NETADM;
5043#if !defined(CONFIG_HAP_LINUX_TPROXY)
5044 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005045#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005046#else /* no TPROXY support */
5047 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005048 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005051#endif
5052 cur_arg += 2;
5053 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005054 }
5055
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005056 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5057#ifdef SO_BINDTODEVICE
5058 if (!*args[cur_arg + 1]) {
5059 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005063 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005064 free(curproxy->conn_src.iface_name);
5065 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5066 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005067 global.last_checks |= LSTCHK_NETADM;
5068#else
5069 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5070 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005071 err_code |= ERR_ALERT | ERR_FATAL;
5072 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005073#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005074 cur_arg += 2;
5075 continue;
5076 }
5077 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005078 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005083 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5084 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5085 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096
5097 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005098 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005099 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005100 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005105 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005106 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005112 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005113 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
5117 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005119 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005120 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
5124 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005125 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005126 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005127 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005131 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005132 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005133 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005134 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005136 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005137 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005138 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005140 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005141 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005143 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005144 }
5145 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005147 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
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 Tarreaua496b602006-12-17 23:15:24 +01005151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159
5160 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005161 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005162 args[0], args[1], args[2], (const char **)args+3);
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], "reqidel")) { /* delete request header from a regex ignoring case */
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_REMOVE, REG_ICASE,
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], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
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_DENY, REG_ICASE,
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 }
5180 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, REG_ICASE,
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 Tarreaubaaee002006-06-26 02:48:02 +02005186 }
5187 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring 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_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005190 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005194 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this 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_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005197 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005198 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005199 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005202 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005203
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 if (curproxy == &defproxy) {
5205 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005209 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005211
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 if (*(args[1]) == 0) {
5213 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005217
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005218 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005219 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5220 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5221 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224 }
5225 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5226 }
5227 else if (*args[2]) {
5228 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5229 file, linenum, args[0], args[2]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
5233
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005234 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005235 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005236 wl->s = strdup(args[1]);
5237 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005238 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 }
5240 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005241 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5243 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005247
Willy Tarreauade5ec42010-01-28 19:33:49 +01005248 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005249 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005250 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005251 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005253 }
5254 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005255 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005256 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005257 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005260 }
5261 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005263 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005264 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
5268 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005269 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275
Willy Tarreauade5ec42010-01-28 19:33:49 +01005276 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005277 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005278 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 }
5282 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005284 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005285 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
5289 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005291 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 }
5296 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005297 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005298
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 if (curproxy == &defproxy) {
5300 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005304 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005305 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 if (*(args[1]) == 0) {
5308 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 }
5312
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005313 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005314 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5315 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5316 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 err_code |= warnif_cond_requires_req(cond, file, linenum);
5321 }
5322 else if (*args[2]) {
5323 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5324 file, linenum, args[0], args[2]);
5325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
5327 }
5328
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005329 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005330 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005331 wl->s = strdup(args[1]);
5332 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334 else if (!strcmp(args[0], "errorloc") ||
5335 !strcmp(args[0], "errorloc302") ||
5336 !strcmp(args[0], "errorloc303")) { /* error location */
5337 int errnum, errlen;
5338 char *err;
5339
Willy Tarreau977b8e42006-12-29 14:19:17 +01005340 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005341 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005342
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005344 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 }
5348
5349 errnum = atol(args[1]);
5350 if (!strcmp(args[0], "errorloc303")) {
5351 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5352 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5353 } else {
5354 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5355 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5356 }
5357
Willy Tarreau0f772532006-12-23 20:51:41 +01005358 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5359 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005360 chunk_destroy(&curproxy->errmsg[rc]);
5361 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005362 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005365
5366 if (rc >= HTTP_ERR_SIZE) {
5367 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5368 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 free(err);
5370 }
5371 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005372 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5373 int errnum, errlen, fd;
5374 char *err;
5375 struct stat stat;
5376
5377 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005379
5380 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005381 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005384 }
5385
5386 fd = open(args[2], O_RDONLY);
5387 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5388 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5389 file, linenum, args[2], args[1]);
5390 if (fd >= 0)
5391 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005394 }
5395
Willy Tarreau27a674e2009-08-17 07:23:33 +02005396 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005397 errlen = stat.st_size;
5398 } else {
5399 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005400 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005402 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005403 }
5404
5405 err = malloc(errlen); /* malloc() must succeed during parsing */
5406 errnum = read(fd, err, errlen);
5407 if (errnum != errlen) {
5408 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5409 file, linenum, args[2], args[1]);
5410 close(fd);
5411 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005414 }
5415 close(fd);
5416
5417 errnum = atol(args[1]);
5418 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5419 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005420 chunk_destroy(&curproxy->errmsg[rc]);
5421 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005422 break;
5423 }
5424 }
5425
5426 if (rc >= HTTP_ERR_SIZE) {
5427 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5428 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005430 free(err);
5431 }
5432 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005433 else if (!strcmp(args[0], "compression")) {
5434 struct comp *comp;
5435 if (curproxy->comp == NULL) {
5436 comp = calloc(1, sizeof(struct comp));
5437 curproxy->comp = comp;
5438 } else {
5439 comp = curproxy->comp;
5440 }
5441
5442 if (!strcmp(args[1], "algo")) {
5443 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005444 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005445
William Lallemand82fe75c2012-10-23 10:25:10 +02005446 cur_arg = 2;
5447 if (!*args[cur_arg]) {
5448 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5449 file, linenum, args[0]);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453 while (*(args[cur_arg])) {
5454 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5455 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5456 file, linenum, args[0], args[cur_arg]);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
William Lallemand552df672012-11-07 13:21:47 +01005460 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5461 curproxy->comp->algos->end(&ctx);
5462 } else {
5463 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5464 file, linenum, args[0], args[cur_arg]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005468 cur_arg ++;
5469 continue;
5470 }
5471 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005472 else if (!strcmp(args[1], "offload")) {
5473 comp->offload = 1;
5474 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005475 else if (!strcmp(args[1], "type")) {
5476 int cur_arg;
5477 cur_arg = 2;
5478 if (!*args[cur_arg]) {
5479 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5480 file, linenum, args[0]);
5481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
5483 }
5484 while (*(args[cur_arg])) {
5485 comp_append_type(comp, args[cur_arg]);
5486 cur_arg ++;
5487 continue;
5488 }
5489 }
5490 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005491 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005492 file, linenum, args[0]);
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
5496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005498 struct cfg_kw_list *kwl;
5499 int index;
5500
5501 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5502 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5503 if (kwl->kw[index].section != CFG_LISTEN)
5504 continue;
5505 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5506 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005507 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005508 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005509 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005512 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005513 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005514 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005515 err_code |= ERR_WARN;
5516 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005517 }
Willy Tarreau93893792009-07-23 13:19:11 +02005518 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005519 }
5520 }
5521 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005522
Willy Tarreau6daf3432008-01-22 16:44:08 +01005523 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 }
Willy Tarreau93893792009-07-23 13:19:11 +02005527 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005528 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530}
5531
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005532int
5533cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5534{
5535
5536 int err_code = 0;
5537 const char *err;
5538
5539 if (!strcmp(args[0], "userlist")) { /* new userlist */
5540 struct userlist *newul;
5541
5542 if (!*args[1]) {
5543 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5544 file, linenum, args[0]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548
5549 err = invalid_char(args[1]);
5550 if (err) {
5551 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5552 file, linenum, *err, args[0], args[1]);
5553 err_code |= ERR_ALERT | ERR_FATAL;
5554 goto out;
5555 }
5556
5557 for (newul = userlist; newul; newul = newul->next)
5558 if (!strcmp(newul->name, args[1])) {
5559 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5560 file, linenum, args[1]);
5561 err_code |= ERR_WARN;
5562 goto out;
5563 }
5564
5565 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5566 if (!newul) {
5567 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5568 err_code |= ERR_ALERT | ERR_ABORT;
5569 goto out;
5570 }
5571
5572 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5573 newul->name = strdup(args[1]);
5574
5575 if (!newul->groupusers | !newul->name) {
5576 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5577 err_code |= ERR_ALERT | ERR_ABORT;
5578 goto out;
5579 }
5580
5581 newul->next = userlist;
5582 userlist = newul;
5583
5584 } else if (!strcmp(args[0], "group")) { /* new group */
5585 int cur_arg, i;
5586 const char *err;
5587
5588 if (!*args[1]) {
5589 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5590 file, linenum, args[0]);
5591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
5594
5595 err = invalid_char(args[1]);
5596 if (err) {
5597 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5598 file, linenum, *err, args[0], args[1]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602
5603 for(i = 0; i < userlist->grpcnt; i++)
5604 if (!strcmp(userlist->groups[i], args[1])) {
5605 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5606 file, linenum, args[1], userlist->name);
5607 err_code |= ERR_ALERT;
5608 goto out;
5609 }
5610
5611 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5612 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5613 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617
5618 cur_arg = 2;
5619
5620 while (*args[cur_arg]) {
5621 if (!strcmp(args[cur_arg], "users")) {
5622 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5623 cur_arg += 2;
5624 continue;
5625 } else {
5626 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5627 file, linenum, args[0]);
5628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
5630 }
5631 }
5632
5633 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5634 } else if (!strcmp(args[0], "user")) { /* new user */
5635 struct auth_users *newuser;
5636 int cur_arg;
5637
5638 if (!*args[1]) {
5639 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5640 file, linenum, args[0]);
5641 err_code |= ERR_ALERT | ERR_FATAL;
5642 goto out;
5643 }
5644
5645 for (newuser = userlist->users; newuser; newuser = newuser->next)
5646 if (!strcmp(newuser->user, args[1])) {
5647 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5648 file, linenum, args[1], userlist->name);
5649 err_code |= ERR_ALERT;
5650 goto out;
5651 }
5652
5653 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5654 if (!newuser) {
5655 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5656 err_code |= ERR_ALERT | ERR_ABORT;
5657 goto out;
5658 }
5659
5660 newuser->user = strdup(args[1]);
5661
5662 newuser->next = userlist->users;
5663 userlist->users = newuser;
5664
5665 cur_arg = 2;
5666
5667 while (*args[cur_arg]) {
5668 if (!strcmp(args[cur_arg], "password")) {
5669#ifndef CONFIG_HAP_CRYPT
5670 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5671 file, linenum);
5672 err_code |= ERR_ALERT;
5673#endif
5674 newuser->pass = strdup(args[cur_arg + 1]);
5675 cur_arg += 2;
5676 continue;
5677 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5678 newuser->pass = strdup(args[cur_arg + 1]);
5679 newuser->flags |= AU_O_INSECURE;
5680 cur_arg += 2;
5681 continue;
5682 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005683 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005684 cur_arg += 2;
5685 continue;
5686 } else {
5687 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5688 file, linenum, args[0]);
5689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
5691 }
5692 }
5693 } else {
5694 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5695 err_code |= ERR_ALERT | ERR_FATAL;
5696 }
5697
5698out:
5699 return err_code;
5700}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701
5702/*
5703 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005704 * Returns the error code, 0 if OK, or any combination of :
5705 * - ERR_ABORT: must abort ASAP
5706 * - ERR_FATAL: we can continue parsing but not start the service
5707 * - ERR_WARN: a warning has been emitted
5708 * - ERR_ALERT: an alert has been emitted
5709 * Only the two first ones can stop processing, the two others are just
5710 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005712int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005714 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 FILE *f;
5716 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005718 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 if ((f=fopen(file,"r")) == NULL)
5721 return -1;
5722
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005723 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005724 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005725 char *end;
5726 char *args[MAX_LINE_ARGS + 1];
5727 char *line = thisline;
5728
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 linenum++;
5730
5731 end = line + strlen(line);
5732
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005733 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5734 /* Check if we reached the limit and the last char is not \n.
5735 * Watch out for the last line without the terminating '\n'!
5736 */
5737 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005738 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005740 }
5741
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005743 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 line++;
5745
5746 arg = 0;
5747 args[arg] = line;
5748
5749 while (*line && arg < MAX_LINE_ARGS) {
5750 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5751 * C equivalent value. Other combinations left unchanged (eg: \1).
5752 */
5753 if (*line == '\\') {
5754 int skip = 0;
5755 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5756 *line = line[1];
5757 skip = 1;
5758 }
5759 else if (line[1] == 'r') {
5760 *line = '\r';
5761 skip = 1;
5762 }
5763 else if (line[1] == 'n') {
5764 *line = '\n';
5765 skip = 1;
5766 }
5767 else if (line[1] == 't') {
5768 *line = '\t';
5769 skip = 1;
5770 }
5771 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005772 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773 unsigned char hex1, hex2;
5774 hex1 = toupper(line[2]) - '0';
5775 hex2 = toupper(line[3]) - '0';
5776 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5777 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5778 *line = (hex1<<4) + hex2;
5779 skip = 3;
5780 }
5781 else {
5782 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005783 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 }
5786 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005787 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 end -= skip;
5789 }
5790 line++;
5791 }
5792 else if (*line == '#' || *line == '\n' || *line == '\r') {
5793 /* end of string, end of loop */
5794 *line = 0;
5795 break;
5796 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005797 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005799 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005800 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801 line++;
5802 args[++arg] = line;
5803 }
5804 else {
5805 line++;
5806 }
5807 }
5808
5809 /* empty line */
5810 if (!**args)
5811 continue;
5812
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005813 if (*line) {
5814 /* we had to stop due to too many args.
5815 * Let's terminate the string, print the offending part then cut the
5816 * last arg.
5817 */
5818 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5819 line++;
5820 *line = '\0';
5821
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005822 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005823 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 args[arg] = line;
5826 }
5827
Willy Tarreau540abe42007-05-02 20:50:16 +02005828 /* zero out remaining args and ensure that at least one entry
5829 * is zeroed out.
5830 */
5831 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 args[arg] = line;
5833 }
5834
Willy Tarreau3842f002009-06-14 11:39:52 +02005835 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005836 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005837 char *tmp;
5838
Willy Tarreau3842f002009-06-14 11:39:52 +02005839 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005840 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005841 for (arg=0; *args[arg+1]; arg++)
5842 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005843 *tmp = '\0'; // fix the next arg to \0
5844 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005845 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005846 else if (!strcmp(args[0], "default")) {
5847 kwm = KWM_DEF;
5848 for (arg=0; *args[arg+1]; arg++)
5849 args[arg] = args[arg+1]; // shift args after inversion
5850 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005851
William Lallemand0f99e342011-10-12 17:50:54 +02005852 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5853 strcmp(args[0], "log") != 0) {
5854 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005855 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005856 }
5857
Willy Tarreau977b8e42006-12-29 14:19:17 +01005858 if (!strcmp(args[0], "listen") ||
5859 !strcmp(args[0], "frontend") ||
5860 !strcmp(args[0], "backend") ||
5861 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005862 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005864 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005865 cursection = strdup(args[0]);
5866 }
5867 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005869 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005870 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005871 }
5872 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005873 confsect = CFG_USERLIST;
5874 free(cursection);
5875 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005876 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005877 else if (!strcmp(args[0], "peers")) {
5878 confsect = CFG_PEERS;
5879 free(cursection);
5880 cursection = strdup(args[0]);
5881 }
5882
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 /* else it's a section keyword */
5884
5885 switch (confsect) {
5886 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005887 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005888 break;
5889 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005890 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005892 case CFG_USERLIST:
5893 err_code |= cfg_parse_users(file, linenum, args, kwm);
5894 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005895 case CFG_PEERS:
5896 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5897 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005899 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005900 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005902
5903 if (err_code & ERR_ABORT)
5904 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005906 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005907 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005909 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005910}
5911
Willy Tarreaubb925012009-07-23 13:36:36 +02005912/*
5913 * Returns the error code, 0 if OK, or any combination of :
5914 * - ERR_ABORT: must abort ASAP
5915 * - ERR_FATAL: we can continue parsing but not start the service
5916 * - ERR_WARN: a warning has been emitted
5917 * - ERR_ALERT: an alert has been emitted
5918 * Only the two first ones can stop processing, the two others are just
5919 * indicators.
5920 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005921int check_config_validity()
5922{
5923 int cfgerr = 0;
5924 struct proxy *curproxy = NULL;
5925 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005926 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005927 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005928 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005929 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005931 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005932 /*
5933 * Now, check for the integrity of all that we have collected.
5934 */
5935
5936 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005937 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938
Willy Tarreau193b8c62012-11-22 00:17:38 +01005939 if (!global.tune.max_http_hdr)
5940 global.tune.max_http_hdr = MAX_HTTP_HDR;
5941
5942 if (!global.tune.cookie_len)
5943 global.tune.cookie_len = CAPTURE_LEN;
5944
5945 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5946
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005947 /* first, we will invert the proxy list order */
5948 curproxy = NULL;
5949 while (proxy) {
5950 struct proxy *next;
5951
5952 next = proxy->next;
5953 proxy->next = curproxy;
5954 curproxy = proxy;
5955 if (!next)
5956 break;
5957 proxy = next;
5958 }
5959
Willy Tarreaubaaee002006-06-26 02:48:02 +02005960 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005961 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005962 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005963 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005964 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005965 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005966 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005967 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005968
Willy Tarreau050536d2012-10-04 08:47:34 +02005969 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005970 /* proxy ID not set, use automatic numbering with first
5971 * spare entry starting with next_pxid.
5972 */
5973 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5974 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5975 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005976 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005977 next_pxid++;
5978
Willy Tarreau55ea7572007-06-17 19:56:27 +02005979
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005981 /* ensure we don't keep listeners uselessly bound */
5982 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 curproxy = curproxy->next;
5984 continue;
5985 }
5986
Willy Tarreau16a21472012-11-19 12:39:59 +01005987 /* number of processes this proxy is bound to */
5988 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5989
Willy Tarreauff01a212009-03-15 13:46:16 +01005990 switch (curproxy->mode) {
5991 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005992 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005993 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005994 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5995 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005996 cfgerr++;
5997 }
5998
5999 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006000 Warning("config : servers will be ignored for %s '%s'.\n",
6001 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006002 break;
6003
6004 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006005 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006006 break;
6007
6008 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006009 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006010 break;
6011 }
6012
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006013 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006014 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006015 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006016 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6017 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006018 cfgerr++;
6019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006021 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006022 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6023 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006024 cfgerr++;
6025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006027 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006028 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6029 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006030 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006031 }
6032 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006033 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006034 /* If no LB algo is set in a backend, and we're not in
6035 * transparent mode, dispatch mode nor proxy mode, we
6036 * want to use balance roundrobin by default.
6037 */
6038 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6039 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006040 }
6041 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006042
Willy Tarreau1620ec32011-08-06 17:05:02 +02006043 if (curproxy->options & PR_O_DISPATCH)
6044 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6045 else if (curproxy->options & PR_O_HTTP_PROXY)
6046 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6047 else if (curproxy->options & PR_O_TRANSP)
6048 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006049
Willy Tarreau1620ec32011-08-06 17:05:02 +02006050 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6051 if (curproxy->options & PR_O_DISABLE404) {
6052 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6053 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6054 err_code |= ERR_WARN;
6055 curproxy->options &= ~PR_O_DISABLE404;
6056 }
6057 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6058 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6059 "send-state", proxy_type_str(curproxy), curproxy->id);
6060 err_code |= ERR_WARN;
6061 curproxy->options &= ~PR_O2_CHK_SNDST;
6062 }
Willy Tarreauef781042010-01-27 11:53:01 +01006063 }
6064
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006065 /* if a default backend was specified, let's find it */
6066 if (curproxy->defbe.name) {
6067 struct proxy *target;
6068
Alex Williams96532db2009-11-01 21:27:13 -05006069 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006070 if (!target) {
6071 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6072 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006073 cfgerr++;
6074 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006075 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6076 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006077 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006078 } else {
6079 free(curproxy->defbe.name);
6080 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006081 /* we force the backend to be present on at least all of
6082 * the frontend's processes.
6083 */
6084 target->bind_proc = curproxy->bind_proc ?
6085 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006086
6087 /* Emit a warning if this proxy also has some servers */
6088 if (curproxy->srv) {
6089 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6090 curproxy->id);
6091 err_code |= ERR_WARN;
6092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 }
6094 }
6095
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006096 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006097 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6098 /* map jump target for ACT_SETBE in req_rep chain */
6099 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006100 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006101 struct proxy *target;
6102
Willy Tarreaua496b602006-12-17 23:15:24 +01006103 if (exp->action != ACT_SETBE)
6104 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006105
Alex Williams96532db2009-11-01 21:27:13 -05006106 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006107 if (!target) {
6108 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6109 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006110 cfgerr++;
6111 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006112 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6113 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006114 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006115 } else {
6116 free((void *)exp->replace);
6117 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006118 /* we force the backend to be present on at least all of
6119 * the frontend's processes.
6120 */
6121 target->bind_proc = curproxy->bind_proc ?
6122 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006123 }
6124 }
6125 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006126
6127 /* find the target proxy for 'use_backend' rules */
6128 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006129 struct proxy *target;
6130
Alex Williams96532db2009-11-01 21:27:13 -05006131 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006132
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006133 if (!target) {
6134 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6135 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006136 cfgerr++;
6137 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006138 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6139 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006140 cfgerr++;
6141 } else {
6142 free((void *)rule->be.name);
6143 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006144 /* we force the backend to be present on at least all of
6145 * the frontend's processes.
6146 */
6147 target->bind_proc = curproxy->bind_proc ?
6148 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006149 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006150 }
6151
6152 /* find the target proxy for 'use_backend' rules */
6153 list_for_each_entry(srule, &curproxy->server_rules, list) {
6154 struct server *target = findserver(curproxy, srule->srv.name);
6155
6156 if (!target) {
6157 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6158 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6159 cfgerr++;
6160 continue;
6161 }
6162 free((void *)srule->srv.name);
6163 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006164 }
6165
Emeric Brunb982a3d2010-01-04 15:45:53 +01006166 /* find the target table for 'stick' rules */
6167 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6168 struct proxy *target;
6169
Emeric Brun1d33b292010-01-04 15:47:17 +01006170 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6171 if (mrule->flags & STK_IS_STORE)
6172 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6173
Emeric Brunb982a3d2010-01-04 15:45:53 +01006174 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006175 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006176 else
6177 target = curproxy;
6178
6179 if (!target) {
6180 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6181 curproxy->id, mrule->table.name);
6182 cfgerr++;
6183 }
6184 else if (target->table.size == 0) {
6185 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6186 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6187 cfgerr++;
6188 }
Willy Tarreau12785782012-04-27 21:37:17 +02006189 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6190 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6192 cfgerr++;
6193 }
6194 else {
6195 free((void *)mrule->table.name);
6196 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006197 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006198 }
6199 }
6200
6201 /* find the target table for 'store response' rules */
6202 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6203 struct proxy *target;
6204
Emeric Brun1d33b292010-01-04 15:47:17 +01006205 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6206
Emeric Brunb982a3d2010-01-04 15:45:53 +01006207 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006208 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006209 else
6210 target = curproxy;
6211
6212 if (!target) {
6213 Alert("Proxy '%s': unable to find store table '%s'.\n",
6214 curproxy->id, mrule->table.name);
6215 cfgerr++;
6216 }
6217 else if (target->table.size == 0) {
6218 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6219 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6220 cfgerr++;
6221 }
Willy Tarreau12785782012-04-27 21:37:17 +02006222 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6223 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006224 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6225 cfgerr++;
6226 }
6227 else {
6228 free((void *)mrule->table.name);
6229 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006230 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006231 }
6232 }
6233
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006234 /* find the target table for 'tcp-request' layer 4 rules */
6235 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6236 struct proxy *target;
6237
Willy Tarreau56123282010-08-06 19:06:56 +02006238 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006239 continue;
6240
6241 if (trule->act_prm.trk_ctr.table.n)
6242 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6243 else
6244 target = curproxy;
6245
6246 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006247 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6248 curproxy->id, trule->act_prm.trk_ctr.table.n,
6249 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006250 cfgerr++;
6251 }
6252 else if (target->table.size == 0) {
6253 Alert("Proxy '%s': table '%s' used but not configured.\n",
6254 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6255 cfgerr++;
6256 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006257 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6258 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6259 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6260 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6261 cfgerr++;
6262 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006263 else {
6264 free(trule->act_prm.trk_ctr.table.n);
6265 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006266 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006267 * to pass a list of counters to track and allocate them right here using
6268 * stktable_alloc_data_type().
6269 */
6270 }
6271 }
6272
Willy Tarreaud1f96522010-08-03 19:34:32 +02006273 /* find the target table for 'tcp-request' layer 6 rules */
6274 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6275 struct proxy *target;
6276
Willy Tarreau56123282010-08-06 19:06:56 +02006277 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006278 continue;
6279
6280 if (trule->act_prm.trk_ctr.table.n)
6281 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6282 else
6283 target = curproxy;
6284
6285 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006286 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6287 curproxy->id, trule->act_prm.trk_ctr.table.n,
6288 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006289 cfgerr++;
6290 }
6291 else if (target->table.size == 0) {
6292 Alert("Proxy '%s': table '%s' used but not configured.\n",
6293 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6294 cfgerr++;
6295 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006296 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6297 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6298 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6299 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6300 cfgerr++;
6301 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006302 else {
6303 free(trule->act_prm.trk_ctr.table.n);
6304 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006305 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006306 * to pass a list of counters to track and allocate them right here using
6307 * stktable_alloc_data_type().
6308 */
6309 }
6310 }
6311
Emeric Brun32da3c42010-09-23 18:39:19 +02006312 if (curproxy->table.peers.name) {
6313 struct peers *curpeers = peers;
6314
6315 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6316 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6317 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006318 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006319 break;
6320 }
6321 }
6322
6323 if (!curpeers) {
6324 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6325 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006326 free((void *)curproxy->table.peers.name);
6327 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006328 cfgerr++;
6329 }
6330 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006331 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6332 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006333 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006334 cfgerr++;
6335 }
6336 }
6337
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006338 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006339 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006340 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6341 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6342 "proxy", curproxy->id);
6343 cfgerr++;
6344 goto out_uri_auth_compat;
6345 }
6346
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006347 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006348 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006349 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006350 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006351
Willy Tarreau95fa4692010-02-01 13:05:50 +01006352 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6353 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006354
6355 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006356 uri_auth_compat_req[i++] = "realm";
6357 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6358 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006359
Willy Tarreau95fa4692010-02-01 13:05:50 +01006360 uri_auth_compat_req[i++] = "unless";
6361 uri_auth_compat_req[i++] = "{";
6362 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6363 uri_auth_compat_req[i++] = "}";
6364 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006365
Willy Tarreauff011f22011-01-06 17:51:27 +01006366 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6367 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006368 cfgerr++;
6369 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006370 }
6371
Willy Tarreauff011f22011-01-06 17:51:27 +01006372 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006373
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006374 if (curproxy->uri_auth->auth_realm) {
6375 free(curproxy->uri_auth->auth_realm);
6376 curproxy->uri_auth->auth_realm = NULL;
6377 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006378
6379 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006380 }
6381out_uri_auth_compat:
6382
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006383 cfgerr += acl_find_targets(curproxy);
6384
Willy Tarreau2738a142006-07-08 17:28:09 +02006385 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006386 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006387 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006388 (!curproxy->timeout.connect ||
6389 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006390 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006391 " | While not properly invalid, you will certainly encounter various problems\n"
6392 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006393 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006394 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006395 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006396 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006397
Willy Tarreau1fa31262007-12-03 00:36:16 +01006398 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6399 * We must still support older configurations, so let's find out whether those
6400 * parameters have been set or must be copied from contimeouts.
6401 */
6402 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006403 if (!curproxy->timeout.tarpit ||
6404 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006405 /* tarpit timeout not set. We search in the following order:
6406 * default.tarpit, curr.connect, default.connect.
6407 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006408 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006409 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006410 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006411 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006412 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006413 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006414 }
6415 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006416 (!curproxy->timeout.queue ||
6417 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006418 /* queue timeout not set. We search in the following order:
6419 * default.queue, curr.connect, default.connect.
6420 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006421 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006422 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006423 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006424 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006425 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006426 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006427 }
6428 }
6429
Willy Tarreau1620ec32011-08-06 17:05:02 +02006430 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006431 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6432 curproxy->check_req = (char *)malloc(curproxy->check_len);
6433 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006434 }
6435
Willy Tarreau193b8c62012-11-22 00:17:38 +01006436 /* ensure that cookie capture length is not too large */
6437 if (curproxy->capture_len >= global.tune.cookie_len) {
6438 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6439 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6440 err_code |= ERR_WARN;
6441 curproxy->capture_len = global.tune.cookie_len - 1;
6442 }
6443
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006444 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006445 if (curproxy->nb_req_cap) {
6446 if (curproxy->mode == PR_MODE_HTTP) {
6447 curproxy->req_cap_pool = create_pool("ptrcap",
6448 curproxy->nb_req_cap * sizeof(char *),
6449 MEM_F_SHARED);
6450 } else {
6451 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6452 proxy_type_str(curproxy), curproxy->id);
6453 err_code |= ERR_WARN;
6454 curproxy->to_log &= ~LW_REQHDR;
6455 curproxy->nb_req_cap = 0;
6456 }
6457 }
6458
6459 if (curproxy->nb_rsp_cap) {
6460 if (curproxy->mode == PR_MODE_HTTP) {
6461 curproxy->rsp_cap_pool = create_pool("ptrcap",
6462 curproxy->nb_rsp_cap * sizeof(char *),
6463 MEM_F_SHARED);
6464 } else {
6465 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6466 proxy_type_str(curproxy), curproxy->id);
6467 err_code |= ERR_WARN;
6468 curproxy->to_log &= ~LW_REQHDR;
6469 curproxy->nb_rsp_cap = 0;
6470 }
6471 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006472
Willy Tarreau196729e2012-05-31 19:30:26 +02006473 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006474 if (!(curproxy->cap & PR_CAP_FE)) {
6475 if (curproxy->logformat_string != default_http_log_format &&
6476 curproxy->logformat_string != default_tcp_log_format &&
6477 curproxy->logformat_string != clf_http_log_format)
6478 free(curproxy->logformat_string);
6479 curproxy->logformat_string = NULL;
6480 }
6481
Willy Tarreau196729e2012-05-31 19:30:26 +02006482 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006483 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006484
6485 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006486 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006487
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 /* first, we will invert the servers list order */
6489 newsrv = NULL;
6490 while (curproxy->srv) {
6491 struct server *next;
6492
6493 next = curproxy->srv->next;
6494 curproxy->srv->next = newsrv;
6495 newsrv = curproxy->srv;
6496 if (!next)
6497 break;
6498 curproxy->srv = next;
6499 }
6500
Willy Tarreaudd701652010-05-25 23:03:02 +02006501 /* assign automatic UIDs to servers which don't have one yet */
6502 next_id = 1;
6503 newsrv = curproxy->srv;
6504 while (newsrv != NULL) {
6505 if (!newsrv->puid) {
6506 /* server ID not set, use automatic numbering with first
6507 * spare entry starting with next_svid.
6508 */
6509 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6510 newsrv->conf.id.key = newsrv->puid = next_id;
6511 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6512 }
6513 next_id++;
6514 newsrv = newsrv->next;
6515 }
6516
Willy Tarreau20697042007-11-15 23:26:18 +01006517 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006518 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519
Willy Tarreau62c3be22012-01-20 13:12:32 +01006520 /*
6521 * If this server supports a maxconn parameter, it needs a dedicated
6522 * tasks to fill the emptied slots when a connection leaves.
6523 * Also, resolve deferred tracking dependency if needed.
6524 */
6525 newsrv = curproxy->srv;
6526 while (newsrv != NULL) {
6527 if (newsrv->minconn > newsrv->maxconn) {
6528 /* Only 'minconn' was specified, or it was higher than or equal
6529 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6530 * this will avoid further useless expensive computations.
6531 */
6532 newsrv->maxconn = newsrv->minconn;
6533 } else if (newsrv->maxconn && !newsrv->minconn) {
6534 /* minconn was not specified, so we set it to maxconn */
6535 newsrv->minconn = newsrv->maxconn;
6536 }
6537
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006538#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006539 if (newsrv->use_ssl || newsrv->check.use_ssl)
6540 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006541#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006542
Willy Tarreau62c3be22012-01-20 13:12:32 +01006543 if (newsrv->trackit) {
6544 struct proxy *px;
6545 struct server *srv;
6546 char *pname, *sname;
6547
6548 pname = newsrv->trackit;
6549 sname = strrchr(pname, '/');
6550
6551 if (sname)
6552 *sname++ = '\0';
6553 else {
6554 sname = pname;
6555 pname = NULL;
6556 }
6557
6558 if (pname) {
6559 px = findproxy(pname, PR_CAP_BE);
6560 if (!px) {
6561 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6562 proxy_type_str(curproxy), curproxy->id,
6563 newsrv->id, pname);
6564 cfgerr++;
6565 goto next_srv;
6566 }
6567 } else
6568 px = curproxy;
6569
6570 srv = findserver(px, sname);
6571 if (!srv) {
6572 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6573 proxy_type_str(curproxy), curproxy->id,
6574 newsrv->id, sname);
6575 cfgerr++;
6576 goto next_srv;
6577 }
6578
6579 if (!(srv->state & SRV_CHECKED)) {
6580 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6581 "tracking as it does not have checks enabled.\n",
6582 proxy_type_str(curproxy), curproxy->id,
6583 newsrv->id, px->id, srv->id);
6584 cfgerr++;
6585 goto next_srv;
6586 }
6587
6588 if (curproxy != px &&
6589 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6590 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6591 "tracking: disable-on-404 option inconsistency.\n",
6592 proxy_type_str(curproxy), curproxy->id,
6593 newsrv->id, px->id, srv->id);
6594 cfgerr++;
6595 goto next_srv;
6596 }
6597
6598 /* if the other server is forced disabled, we have to do the same here */
6599 if (srv->state & SRV_MAINTAIN) {
6600 newsrv->state |= SRV_MAINTAIN;
6601 newsrv->state &= ~SRV_RUNNING;
6602 newsrv->health = 0;
6603 }
6604
6605 newsrv->track = srv;
6606 newsrv->tracknext = srv->tracknext;
6607 srv->tracknext = newsrv;
6608
6609 free(newsrv->trackit);
6610 newsrv->trackit = NULL;
6611 }
6612 next_srv:
6613 newsrv = newsrv->next;
6614 }
6615
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006616 /* We have to initialize the server lookup mechanism depending
6617 * on what LB algorithm was choosen.
6618 */
6619
6620 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6621 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6622 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006623 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6624 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6625 init_server_map(curproxy);
6626 } else {
6627 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6628 fwrr_init_server_groups(curproxy);
6629 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006630 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006631
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006632 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006633 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6634 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6635 fwlc_init_server_tree(curproxy);
6636 } else {
6637 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6638 fas_init_server_tree(curproxy);
6639 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006640 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006641
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006642 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006643 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6644 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6645 chash_init_server_tree(curproxy);
6646 } else {
6647 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6648 init_server_map(curproxy);
6649 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006650 break;
6651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006652
6653 if (curproxy->options & PR_O_LOGASAP)
6654 curproxy->to_log &= ~LW_BYTES;
6655
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006656 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006657 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006658 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6659 proxy_type_str(curproxy), curproxy->id);
6660 err_code |= ERR_WARN;
6661 }
6662
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006663 if (curproxy->mode != PR_MODE_HTTP) {
6664 int optnum;
6665
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006666 if (curproxy->uri_auth) {
6667 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6668 proxy_type_str(curproxy), curproxy->id);
6669 err_code |= ERR_WARN;
6670 curproxy->uri_auth = NULL;
6671 }
6672
Willy Tarreau87cf5142011-08-19 22:57:24 +02006673 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006674 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6675 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6676 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006677 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006678 }
6679
6680 if (curproxy->options & PR_O_ORGTO) {
6681 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6682 "originalto", proxy_type_str(curproxy), curproxy->id);
6683 err_code |= ERR_WARN;
6684 curproxy->options &= ~PR_O_ORGTO;
6685 }
6686
6687 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6688 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6689 (curproxy->cap & cfg_opts[optnum].cap) &&
6690 (curproxy->options & cfg_opts[optnum].val)) {
6691 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6692 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6693 err_code |= ERR_WARN;
6694 curproxy->options &= ~cfg_opts[optnum].val;
6695 }
6696 }
6697
6698 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6699 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6700 (curproxy->cap & cfg_opts2[optnum].cap) &&
6701 (curproxy->options2 & cfg_opts2[optnum].val)) {
6702 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6703 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6704 err_code |= ERR_WARN;
6705 curproxy->options2 &= ~cfg_opts2[optnum].val;
6706 }
6707 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006708
Willy Tarreauefa5f512010-03-30 20:13:29 +02006709#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006710 if (curproxy->conn_src.bind_hdr_occ) {
6711 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006712 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006713 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006714 err_code |= ERR_WARN;
6715 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006716#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006717 }
6718
Willy Tarreaubaaee002006-06-26 02:48:02 +02006719 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006720 * ensure that we're not cross-dressing a TCP server into HTTP.
6721 */
6722 newsrv = curproxy->srv;
6723 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006724 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006725 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6726 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006727 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006728 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006729
Willy Tarreau0cec3312011-10-31 13:49:26 +01006730 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6731 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6732 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6733 err_code |= ERR_WARN;
6734 }
6735
Willy Tarreauefa5f512010-03-30 20:13:29 +02006736#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006737 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6738 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006739 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 +01006740 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006741 err_code |= ERR_WARN;
6742 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006743#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006744 newsrv = newsrv->next;
6745 }
6746
Willy Tarreauc1a21672009-08-16 22:37:44 +02006747 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006748 if (!curproxy->accept)
6749 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006750
Willy Tarreauc1a21672009-08-16 22:37:44 +02006751 if (curproxy->tcp_req.inspect_delay ||
6752 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006753 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006754
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006755 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006756 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006757 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006758 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006759
6760 /* both TCP and HTTP must check switching rules */
6761 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6762 }
6763
6764 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006765 if (curproxy->tcp_req.inspect_delay ||
6766 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6767 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6768
Emeric Brun97679e72010-09-23 17:56:44 +02006769 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6770 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6771
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006772 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006773 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006774 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006775 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006776
6777 /* If the backend does requires RDP cookie persistence, we have to
6778 * enable the corresponding analyser.
6779 */
6780 if (curproxy->options2 & PR_O2_RDPC_PRST)
6781 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6782 }
6783
Emeric Brunc52962f2012-11-15 18:28:02 +01006784#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006785 /* Configure SSL for each bind line.
6786 * Note: if configuration fails at some point, the ->ctx member
6787 * remains NULL so that listeners can later detach.
6788 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006789 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006790 if (!bind_conf->is_ssl) {
6791 if (bind_conf->default_ctx) {
6792 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6793 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6794 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006795 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006796 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006797 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006798 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006799 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006800 cfgerr++;
6801 continue;
6802 }
6803
Emeric Brun4b3091e2012-09-24 15:48:52 +02006804 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006805 Alert("Unable to allocate SSL session cache.\n");
6806 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006807 continue;
6808 }
6809
Emeric Brunfc0421f2012-09-07 17:30:07 +02006810 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006811 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006812 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006813#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006814
Willy Tarreaue6b98942007-10-29 01:09:36 +01006815 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006816 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006817 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006818 if (!listener->luid) {
6819 /* listener ID not set, use automatic numbering with first
6820 * spare entry starting with next_luid.
6821 */
6822 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6823 listener->conf.id.key = listener->luid = next_id;
6824 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006825 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006826 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006827
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006828 /* enable separate counters */
6829 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6830 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006831 if (!listener->name)
6832 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006833 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006834
Willy Tarreaue6b98942007-10-29 01:09:36 +01006835 if (curproxy->options & PR_O_TCP_NOLING)
6836 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006837 if (!listener->maxconn)
6838 listener->maxconn = curproxy->maxconn;
6839 if (!listener->backlog)
6840 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006841 if (!listener->maxaccept)
6842 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6843
6844 /* we want to have an optimal behaviour on single process mode to
6845 * maximize the work at once, but in multi-process we want to keep
6846 * some fairness between processes, so we target half of the max
6847 * number of events to be balanced over all the processes the proxy
6848 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6849 * used to disable the limit.
6850 */
6851 if (listener->maxaccept > 0) {
6852 if (nbproc > 1)
6853 listener->maxaccept = (listener->maxaccept + 1) / 2;
6854 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6855 }
6856
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006857 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006858 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006859 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006860 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006861
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006862 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6863 listener->options |= LI_O_TCP_RULES;
6864
Willy Tarreaude3041d2010-05-31 10:56:17 +02006865 if (curproxy->mon_mask.s_addr)
6866 listener->options |= LI_O_CHK_MONNET;
6867
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006868 /* smart accept mode is automatic in HTTP mode */
6869 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006870 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006871 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6872 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006873 }
6874
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006875 /* Release unused SSL configs */
6876 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6877 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006878 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006879#ifdef USE_OPENSSL
6880 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006881 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006882 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006883 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006884 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006885#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006886 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006887
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006888 /* Check multi-process mode compatibility for the current proxy */
6889 if (global.nbproc > 1) {
6890 int nbproc = 0;
6891 if (curproxy->bind_proc) {
6892 int proc;
6893 for (proc = 0; proc < global.nbproc; proc++) {
6894 if (curproxy->bind_proc & (1 << proc)) {
6895 nbproc++;
6896 }
6897 }
6898 } else {
6899 nbproc = global.nbproc;
6900 }
6901 if (curproxy->table.peers.name) {
6902 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6903 curproxy->id);
6904 cfgerr++;
6905 }
6906 if (nbproc > 1) {
6907 if (curproxy->uri_auth) {
6908 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6909 curproxy->id);
6910 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6911 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6912 curproxy->id);
6913 }
6914 }
6915 if (curproxy->appsession_name) {
6916 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6917 curproxy->id);
6918 }
6919 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6920 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6921 curproxy->id);
6922 }
6923 }
6924 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006925
6926 /* create the task associated with the proxy */
6927 curproxy->task = task_new();
6928 if (curproxy->task) {
6929 curproxy->task->context = curproxy;
6930 curproxy->task->process = manage_proxy;
6931 /* no need to queue, it will be done automatically if some
6932 * listener gets limited.
6933 */
6934 curproxy->task->expire = TICK_ETERNITY;
6935 } else {
6936 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6937 curproxy->id);
6938 cfgerr++;
6939 }
6940
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941 curproxy = curproxy->next;
6942 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006943
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006944 /* Check multi-process mode compatibility */
6945 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006946 if (global.stats_fe && !global.stats_fe->bind_proc) {
6947 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 +01006948 }
6949 }
6950
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006951 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6952 struct auth_users *curuser;
6953 int g;
6954
6955 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6956 unsigned int group_mask = 0;
6957 char *group = NULL;
6958
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006959 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006960 continue;
6961
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006962 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006963
6964 for (g = 0; g < curuserlist->grpcnt; g++)
6965 if (!strcmp(curuserlist->groups[g], group))
6966 break;
6967
6968 if (g == curuserlist->grpcnt) {
6969 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6970 curuserlist->name, group, curuser->user);
6971 err_code |= ERR_ALERT | ERR_FATAL;
6972 goto out;
6973 }
6974
6975 group_mask |= (1 << g);
6976 }
6977
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006978 free(curuser->u.groups);
6979 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006980 }
6981
6982 for (g = 0; g < curuserlist->grpcnt; g++) {
6983 char *user = NULL;
6984
6985 if (!curuserlist->groupusers[g])
6986 continue;
6987
6988 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6989 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6990 if (!strcmp(curuser->user, user))
6991 break;
6992
6993 if (!curuser) {
6994 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6995 curuserlist->name, user, curuserlist->groups[g]);
6996 err_code |= ERR_ALERT | ERR_FATAL;
6997 goto out;
6998 }
6999
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007000 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007001 }
7002
7003 free(curuserlist->groupusers[g]);
7004 }
7005
7006 free(curuserlist->groupusers);
7007
7008#ifdef DEBUG_AUTH
7009 for (g = 0; g < curuserlist->grpcnt; g++) {
7010 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7011
7012 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007013 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007014 fprintf(stderr, " %s", curuser->user);
7015 }
7016
7017 fprintf(stderr, "\n");
7018 }
7019#endif
7020
Willy Tarreaufbb78422011-06-05 15:38:35 +02007021 }
7022
7023 /* automatically compute fullconn if not set. We must not do it in the
7024 * loop above because cross-references are not yet fully resolved.
7025 */
7026 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7027 /* If <fullconn> is not set, let's set it to 10% of the sum of
7028 * the possible incoming frontend's maxconns.
7029 */
7030 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7031 struct proxy *fe;
7032 int total = 0;
7033
7034 /* sum up the number of maxconns of frontends which
7035 * reference this backend at least once or which are
7036 * the same one ('listen').
7037 */
7038 for (fe = proxy; fe; fe = fe->next) {
7039 struct switching_rule *rule;
7040 struct hdr_exp *exp;
7041 int found = 0;
7042
7043 if (!(fe->cap & PR_CAP_FE))
7044 continue;
7045
7046 if (fe == curproxy) /* we're on a "listen" instance */
7047 found = 1;
7048
7049 if (fe->defbe.be == curproxy) /* "default_backend" */
7050 found = 1;
7051
7052 /* check if a "use_backend" rule matches */
7053 if (!found) {
7054 list_for_each_entry(rule, &fe->switching_rules, list) {
7055 if (rule->be.backend == curproxy) {
7056 found = 1;
7057 break;
7058 }
7059 }
7060 }
7061
7062 /* check if a "reqsetbe" rule matches */
7063 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7064 if (exp->action == ACT_SETBE &&
7065 (struct proxy *)exp->replace == curproxy) {
7066 found = 1;
7067 break;
7068 }
7069 }
7070
7071 /* now we've checked all possible ways to reference a backend
7072 * from a frontend.
7073 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007074 if (!found)
7075 continue;
7076 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007077 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007078 /* we have the sum of the maxconns in <total>. We only
7079 * keep 10% of that sum to set the default fullconn, with
7080 * a hard minimum of 1 (to avoid a divide by zero).
7081 */
7082 curproxy->fullconn = (total + 9) / 10;
7083 if (!curproxy->fullconn)
7084 curproxy->fullconn = 1;
7085 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007086 }
7087
Willy Tarreau056f5682010-06-06 15:51:11 +02007088 /* initialize stick-tables on backend capable proxies. This must not
7089 * be done earlier because the data size may be discovered while parsing
7090 * other proxies.
7091 */
7092 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007093 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007094
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007095 /*
7096 * Recount currently required checks.
7097 */
7098
7099 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7100 int optnum;
7101
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007102 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7103 if (curproxy->options & cfg_opts[optnum].val)
7104 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007105
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007106 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7107 if (curproxy->options2 & cfg_opts2[optnum].val)
7108 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007109 }
7110
Willy Tarreau122541c2011-09-07 21:24:49 +02007111 if (peers) {
7112 struct peers *curpeers = peers, **last;
7113 struct peer *p, *pb;
7114
7115 /* Remove all peers sections which don't have a valid listener.
7116 * This can happen when a peers section is never referenced and
7117 * does not contain a local peer.
7118 */
7119 last = &peers;
7120 while (*last) {
7121 curpeers = *last;
7122 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007123 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007124 last = &curpeers->next;
7125 continue;
7126 }
7127
7128 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7129 curpeers->id, localpeer);
7130
7131 p = curpeers->remote;
7132 while (p) {
7133 pb = p->next;
7134 free(p->id);
7135 free(p);
7136 p = pb;
7137 }
7138
7139 /* Destroy and unlink this curpeers section.
7140 * Note: curpeers is backed up into *last.
7141 */
7142 free(curpeers->id);
7143 curpeers = curpeers->next;
7144 free(*last);
7145 *last = curpeers;
7146 }
7147 }
7148
Willy Tarreau34eb6712011-10-24 18:15:04 +02007149 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007150 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007151 MEM_F_SHARED);
7152
Willy Tarreaubb925012009-07-23 13:36:36 +02007153 if (cfgerr > 0)
7154 err_code |= ERR_ALERT | ERR_FATAL;
7155 out:
7156 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157}
7158
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007159/*
7160 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7161 * parsing sessions.
7162 */
7163void cfg_register_keywords(struct cfg_kw_list *kwl)
7164{
7165 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7166}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007167
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007168/*
7169 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7170 */
7171void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7172{
7173 LIST_DEL(&kwl->list);
7174 LIST_INIT(&kwl->list);
7175}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007176
7177/*
7178 * Local variables:
7179 * c-indent-level: 8
7180 * c-basic-offset: 8
7181 * End:
7182 */