blob: 2c8faadb3280427f156fcb324799f22bd2651625 [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;
William Lallemand0f99e342011-10-12 17:50:54 +02001085 struct logsrv *logsrv;
1086
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 if (*(args[1]) == 0 || *(args[2]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 }
William Lallemand0f99e342011-10-12 17:50:54 +02001092
1093 logsrv = calloc(1, sizeof(struct logsrv));
1094
1095 logsrv->facility = get_log_facility(args[2]);
1096 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001099 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 }
1101
William Lallemand0f99e342011-10-12 17:50:54 +02001102 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001104 logsrv->level = get_log_level(args[3]);
1105 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001106 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001108 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109 }
1110 }
1111
William Lallemand0f99e342011-10-12 17:50:54 +02001112 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001113 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001114 logsrv->minlvl = get_log_level(args[4]);
1115 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001116 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001118 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001119 }
1120 }
1121
Willy Tarreau902636f2013-03-10 19:44:48 +01001122 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001123 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001124 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001126 free(logsrv);
1127 goto out;
1128 }
1129 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001130
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001131 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001132 if (port1 != port2) {
1133 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1134 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001135 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001136 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001137 goto out;
1138 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001139
William Lallemand0f99e342011-10-12 17:50:54 +02001140 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001141 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001142 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144
William Lallemand0f99e342011-10-12 17:50:54 +02001145 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001146 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001147 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1148 char *name;
1149 int len;
1150
1151 if (global.log_send_hostname != NULL) {
1152 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1153 err_code |= ERR_ALERT;
1154 goto out;
1155 }
1156
1157 if (*(args[1]))
1158 name = args[1];
1159 else
1160 name = hostname;
1161
1162 len = strlen(name);
1163
1164 /* We'll add a space after the name to respect the log format */
1165 free(global.log_send_hostname);
1166 global.log_send_hostname = malloc(len + 2);
1167 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1168 }
Kevinm48936af2010-12-22 16:08:21 +00001169 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1170 if (*(args[1]) == 0) {
1171 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 free(global.log_tag);
1176 global.log_tag = strdup(args[1]);
1177 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001178 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1179 if (global.spread_checks != 0) {
1180 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001181 err_code |= ERR_ALERT;
1182 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001183 }
1184 if (*(args[1]) == 0) {
1185 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001188 }
1189 global.spread_checks = atol(args[1]);
1190 if (global.spread_checks < 0 || global.spread_checks > 50) {
1191 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001192 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001194 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001195 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1196#ifdef USE_CPU_AFFINITY
1197 int cur_arg, i;
1198 unsigned int proc = 0;
1199 unsigned long cpus = 0;
1200
1201 if (strcmp(args[1], "all") == 0)
1202 proc = 0xFFFFFFFF;
1203 else if (strcmp(args[1], "odd") == 0)
1204 proc = 0x55555555;
1205 else if (strcmp(args[1], "even") == 0)
1206 proc = 0xAAAAAAAA;
1207 else {
1208 proc = atoi(args[1]);
1209 if (proc >= 1 && proc <= 32)
1210 proc = 1 << (proc - 1);
1211 }
1212
1213 if (!proc || !*args[2]) {
1214 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",
1215 file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218 }
1219
1220 cur_arg = 2;
1221 while (*args[cur_arg]) {
1222 unsigned int low, high;
1223
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001224 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001225 char *dash = strchr(args[cur_arg], '-');
1226
1227 low = high = str2uic(args[cur_arg]);
1228 if (dash)
1229 high = str2uic(dash + 1);
1230
1231 if (high < low) {
1232 unsigned int swap = low;
1233 low = high;
1234 high = swap;
1235 }
1236
1237 if (low < 0 || high >= sizeof(long) * 8) {
1238 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1239 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243
1244 while (low <= high)
1245 cpus |= 1UL << low++;
1246 }
1247 else {
1248 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1249 file, linenum, args[0], args[cur_arg]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253 cur_arg++;
1254 }
1255 for (i = 0; i < 32; i++)
1256 if (proc & (1 << i))
1257 global.cpu_map[i] = cpus;
1258#else
1259 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262#endif
1263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001264 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001265 struct cfg_kw_list *kwl;
1266 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001267 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001268
1269 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1270 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1271 if (kwl->kw[index].section != CFG_GLOBAL)
1272 continue;
1273 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001274 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001275 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001276 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001277 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001278 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001279 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001280 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001281 err_code |= ERR_WARN;
1282 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001283 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001284 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001285 }
1286 }
1287 }
1288
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001290 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001292
Willy Tarreau058e9072009-07-20 09:30:05 +02001293 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001294 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296}
1297
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001298void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001300 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001301 defproxy.mode = PR_MODE_TCP;
1302 defproxy.state = PR_STNEW;
1303 defproxy.maxconn = cfg_maxpconn;
1304 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001305
1306 defproxy.defsrv.inter = DEF_CHKINTR;
1307 defproxy.defsrv.fastinter = 0;
1308 defproxy.defsrv.downinter = 0;
1309 defproxy.defsrv.rise = DEF_RISETIME;
1310 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001311 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001312 defproxy.defsrv.maxqueue = 0;
1313 defproxy.defsrv.minconn = 0;
1314 defproxy.defsrv.maxconn = 0;
1315 defproxy.defsrv.slowstart = 0;
1316 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1317 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1318 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319}
1320
Willy Tarreauade5ec42010-01-28 19:33:49 +01001321
1322static int create_cond_regex_rule(const char *file, int line,
1323 struct proxy *px, int dir, int action, int flags,
1324 const char *cmd, const char *reg, const char *repl,
1325 const char **cond_start)
1326{
1327 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001328 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001329 const char *err;
1330 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001331 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001332
1333 if (px == &defproxy) {
1334 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto err;
1337 }
1338
1339 if (*reg == 0) {
1340 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto err;
1343 }
1344
1345 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1346 err_code |= ERR_WARN;
1347
Willy Tarreau5321c422010-01-28 20:35:13 +01001348 if (cond_start &&
1349 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001350 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1351 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1352 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto err;
1355 }
1356 }
1357 else if (cond_start && **cond_start) {
1358 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1359 file, line, cmd, *cond_start);
1360 err_code |= ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001364 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001365 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001366 else
1367 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001368
Willy Tarreauade5ec42010-01-28 19:33:49 +01001369 preg = calloc(1, sizeof(regex_t));
1370 if (!preg) {
1371 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1372 err_code = ERR_ALERT | ERR_FATAL;
1373 goto err;
1374 }
1375
1376 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1377 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1378 err_code = ERR_ALERT | ERR_FATAL;
1379 goto err;
1380 }
1381
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001382 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001383 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001384 if (repl && err) {
1385 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1386 file, line, cmd, *err);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto err;
1389 }
1390
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001391 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001392 err_code |= ERR_WARN;
1393
Willy Tarreauf4068b62012-05-08 17:37:49 +02001394 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 return err_code;
1396 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001397 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001398 free(preg);
1399 return err_code;
1400}
1401
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001403 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001404 * Returns the error code, 0 if OK, or any combination of :
1405 * - ERR_ABORT: must abort ASAP
1406 * - ERR_FATAL: we can continue parsing but not start the service
1407 * - ERR_WARN: a warning has been emitted
1408 * - ERR_ALERT: an alert has been emitted
1409 * Only the two first ones can stop processing, the two others are just
1410 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001412int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1413{
1414 static struct peers *curpeers = NULL;
1415 struct peer *newpeer = NULL;
1416 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001417 struct bind_conf *bind_conf;
1418 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001419 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001420 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001421
1422 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001423 if (!*args[1]) {
1424 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto out;
1427 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001428
1429 err = invalid_char(args[1]);
1430 if (err) {
1431 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1432 file, linenum, *err, args[0], args[1]);
1433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001434 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001435 }
1436
1437 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1438 /*
1439 * If there are two proxies with the same name only following
1440 * combinations are allowed:
1441 */
1442 if (strcmp(curpeers->id, args[1]) == 0) {
1443 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1444 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1445 err_code |= ERR_WARN;
1446 }
1447 }
1448
1449 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1450 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1451 err_code |= ERR_ALERT | ERR_ABORT;
1452 goto out;
1453 }
1454
1455 curpeers->next = peers;
1456 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001457 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001458 curpeers->conf.line = linenum;
1459 curpeers->last_change = now.tv_sec;
1460 curpeers->id = strdup(args[1]);
1461 }
1462 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001463 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001464 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001465 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001466
1467 if (!*args[2]) {
1468 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1469 file, linenum, args[0]);
1470 err_code |= ERR_ALERT | ERR_FATAL;
1471 goto out;
1472 }
1473
1474 err = invalid_char(args[1]);
1475 if (err) {
1476 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1477 file, linenum, *err, args[1]);
1478 err_code |= ERR_ALERT | ERR_FATAL;
1479 goto out;
1480 }
1481
1482 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1483 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1484 err_code |= ERR_ALERT | ERR_ABORT;
1485 goto out;
1486 }
1487
1488 /* the peers are linked backwards first */
1489 curpeers->count++;
1490 newpeer->next = curpeers->remote;
1491 curpeers->remote = newpeer;
1492 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001493 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001494 newpeer->conf.line = linenum;
1495
1496 newpeer->last_change = now.tv_sec;
1497 newpeer->id = strdup(args[1]);
1498
Willy Tarreau902636f2013-03-10 19:44:48 +01001499 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001500 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001501 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001504 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001505
1506 proto = protocol_by_family(sk->ss_family);
1507 if (!proto || !proto->connect) {
1508 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1509 file, linenum, args[0], args[1]);
1510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
1512 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001513
1514 if (port1 != port2) {
1515 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1516 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001517 err_code |= ERR_ALERT | ERR_FATAL;
1518 goto out;
1519 }
1520
Willy Tarreau2aa38802013-02-20 19:20:59 +01001521 if (!port1) {
1522 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1523 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 err_code |= ERR_ALERT | ERR_FATAL;
1525 goto out;
1526 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001527
Emeric Brun32da3c42010-09-23 18:39:19 +02001528 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001529 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001530 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001531 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001532
Emeric Brun32da3c42010-09-23 18:39:19 +02001533 if (strcmp(newpeer->id, localpeer) == 0) {
1534 /* Current is local peer, it define a frontend */
1535 newpeer->local = 1;
1536
1537 if (!curpeers->peers_fe) {
1538 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1540 err_code |= ERR_ALERT | ERR_ABORT;
1541 goto out;
1542 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001543
Willy Tarreau237250c2011-07-29 01:49:03 +02001544 init_new_proxy(curpeers->peers_fe);
1545 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001546
1547 curpeers->peers_fe->last_change = now.tv_sec;
1548 curpeers->peers_fe->id = strdup(args[1]);
1549 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001550 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001551 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1552 curpeers->peers_fe->timeout.connect = 5000;
1553 curpeers->peers_fe->accept = peer_accept;
1554 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001555 curpeers->peers_fe->conf.file = strdup(file);
1556 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001557
1558 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1559
Willy Tarreau902636f2013-03-10 19:44:48 +01001560 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1561 if (errmsg && *errmsg) {
1562 indent_msg(&errmsg, 2);
1563 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001564 }
1565 else
1566 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1567 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001568 err_code |= ERR_FATAL;
1569 goto out;
1570 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001571
1572 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1573 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1574 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1575 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1576 l->accept = session_accept;
1577 l->handler = process_session;
1578 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1579 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1580 global.maxsock += l->maxconn;
1581 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001582 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001583 else {
1584 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1585 file, linenum, args[0], args[1],
1586 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1587 err_code |= ERR_FATAL;
1588 goto out;
1589 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001590 }
1591 } /* neither "peer" nor "peers" */
1592 else if (*args[0] != 0) {
1593 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
1596 }
1597
1598out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001599 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001600 return err_code;
1601}
1602
1603
Willy Tarreau3842f002009-06-14 11:39:52 +02001604int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605{
1606 static struct proxy *curproxy = NULL;
1607 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001608 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001609 int rc;
1610 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001611 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001612 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001613 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001614 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001615 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616
Willy Tarreau977b8e42006-12-29 14:19:17 +01001617 if (!strcmp(args[0], "listen"))
1618 rc = PR_CAP_LISTEN;
1619 else if (!strcmp(args[0], "frontend"))
1620 rc = PR_CAP_FE | PR_CAP_RS;
1621 else if (!strcmp(args[0], "backend"))
1622 rc = PR_CAP_BE | PR_CAP_RS;
1623 else if (!strcmp(args[0], "ruleset"))
1624 rc = PR_CAP_RS;
1625 else
1626 rc = PR_CAP_NONE;
1627
1628 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 if (!*args[1]) {
1630 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1631 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1632 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_ALERT | ERR_ABORT;
1634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001636
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001637 err = invalid_char(args[1]);
1638 if (err) {
1639 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1640 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001642 }
1643
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001644 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1645 /*
1646 * If there are two proxies with the same name only following
1647 * combinations are allowed:
1648 *
1649 * listen backend frontend ruleset
1650 * listen - - - -
1651 * backend - - OK -
1652 * frontend - OK - -
1653 * ruleset - - - -
1654 */
1655
1656 if (!strcmp(curproxy->id, args[1]) &&
1657 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1658 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001659 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1660 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1661 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001663 }
1664 }
1665
Willy Tarreaubaaee002006-06-26 02:48:02 +02001666 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1667 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_ABORT;
1669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001671
Willy Tarreau97cb7802010-01-03 20:23:58 +01001672 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 curproxy->next = proxy;
1674 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001675 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001676 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001677 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001679 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001680
1681 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001682 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001683 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001684
Willy Tarreau4348fad2012-09-20 16:48:07 +02001685 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1686
Willy Tarreau902636f2013-03-10 19:44:48 +01001687 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1688 if (errmsg && *errmsg) {
1689 indent_msg(&errmsg, 2);
1690 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001691 }
1692 else
1693 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1694 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001695 err_code |= ERR_FATAL;
1696 goto out;
1697 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001698
Willy Tarreau4348fad2012-09-20 16:48:07 +02001699 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001700 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702 }
1703
1704 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001705 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001706 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001707
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001710 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001711 curproxy->no_options = defproxy.no_options;
1712 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001713 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001714 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001715 curproxy->except_net = defproxy.except_net;
1716 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001717 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001718 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001720 if (defproxy.fwdfor_hdr_len) {
1721 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1722 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1723 }
1724
Willy Tarreaub86db342009-11-30 11:50:16 +01001725 if (defproxy.orgto_hdr_len) {
1726 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1727 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1728 }
1729
Mark Lamourinec2247f02012-01-04 13:02:01 -05001730 if (defproxy.server_id_hdr_len) {
1731 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1732 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1733 }
1734
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735 if (curproxy->cap & PR_CAP_FE) {
1736 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001737 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001738 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001739
1740 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001741 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1742 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743
1744 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746
Willy Tarreau977b8e42006-12-29 14:19:17 +01001747 if (curproxy->cap & PR_CAP_BE) {
1748 curproxy->fullconn = defproxy.fullconn;
1749 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001750
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001751 if (defproxy.check_req) {
1752 curproxy->check_req = calloc(1, defproxy.check_len);
1753 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1754 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001755 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001757 if (defproxy.expect_str) {
1758 curproxy->expect_str = strdup(defproxy.expect_str);
1759 if (defproxy.expect_regex) {
1760 /* note: this regex is known to be valid */
1761 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1762 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1763 }
1764 }
1765
Willy Tarreau67402132012-05-31 20:40:20 +02001766 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001767 if (defproxy.cookie_name)
1768 curproxy->cookie_name = strdup(defproxy.cookie_name);
1769 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001770 if (defproxy.cookie_domain)
1771 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001772
Willy Tarreau31936852010-10-06 16:59:56 +02001773 if (defproxy.cookie_maxidle)
1774 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1775
1776 if (defproxy.cookie_maxlife)
1777 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1778
Emeric Brun647caf12009-06-30 17:57:00 +02001779 if (defproxy.rdp_cookie_name)
1780 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1781 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1782
Willy Tarreau01732802007-11-01 22:48:15 +01001783 if (defproxy.url_param_name)
1784 curproxy->url_param_name = strdup(defproxy.url_param_name);
1785 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001786
Benoitaffb4812009-03-25 13:02:10 +01001787 if (defproxy.hh_name)
1788 curproxy->hh_name = strdup(defproxy.hh_name);
1789 curproxy->hh_len = defproxy.hh_len;
1790 curproxy->hh_match_domain = defproxy.hh_match_domain;
1791
Willy Tarreauef9a3602012-12-08 22:29:20 +01001792 if (defproxy.conn_src.iface_name)
1793 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1794 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1795 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001796 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001798 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 if (defproxy.capture_name)
1800 curproxy->capture_name = strdup(defproxy.capture_name);
1801 curproxy->capture_namelen = defproxy.capture_namelen;
1802 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804
Willy Tarreau977b8e42006-12-29 14:19:17 +01001805 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001806 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001807 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001808 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001809 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 curproxy->uri_auth = defproxy.uri_auth;
1811 curproxy->mon_net = defproxy.mon_net;
1812 curproxy->mon_mask = defproxy.mon_mask;
1813 if (defproxy.monitor_uri)
1814 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1815 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001816 if (defproxy.defbe.name)
1817 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001818
1819 /* get either a pointer to the logformat string or a copy of it */
1820 curproxy->logformat_string = defproxy.logformat_string;
1821 if (curproxy->logformat_string &&
1822 curproxy->logformat_string != default_http_log_format &&
1823 curproxy->logformat_string != default_tcp_log_format &&
1824 curproxy->logformat_string != clf_http_log_format)
1825 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001826 }
1827
1828 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001829 curproxy->timeout.connect = defproxy.timeout.connect;
1830 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001831 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001832 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001833 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001834 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001835 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001836 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001837 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 }
1839
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001841
1842 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001843 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001844 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001845 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001846 LIST_INIT(&node->list);
1847 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1848 }
1849
Willy Tarreau196729e2012-05-31 19:30:26 +02001850 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1851 if (curproxy->uniqueid_format_string)
1852 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001853
1854 /* copy default header unique id */
1855 if (defproxy.header_unique_id)
1856 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1857
William Lallemand82fe75c2012-10-23 10:25:10 +02001858 /* default compression options */
1859 if (defproxy.comp != NULL) {
1860 curproxy->comp = calloc(1, sizeof(struct comp));
1861 curproxy->comp->algos = defproxy.comp->algos;
1862 curproxy->comp->types = defproxy.comp->types;
1863 }
1864
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001866 curproxy->conf.used_listener_id = EB_ROOT;
1867 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001868
Willy Tarreau93893792009-07-23 13:19:11 +02001869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001870 }
1871 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1872 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001873 /* FIXME-20070101: we should do this too at the end of the
1874 * config parsing to free all default values.
1875 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001876 free(defproxy.check_req);
1877 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001878 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001879 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001880 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001881 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001882 free(defproxy.capture_name);
1883 free(defproxy.monitor_uri);
1884 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001885 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001886 free(defproxy.fwdfor_hdr_name);
1887 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001888 free(defproxy.orgto_hdr_name);
1889 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001890 free(defproxy.server_id_hdr_name);
1891 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001892 free(defproxy.expect_str);
1893 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001894
Willy Tarreau39b06652012-06-01 10:58:06 +02001895 if (defproxy.logformat_string != default_http_log_format &&
1896 defproxy.logformat_string != default_tcp_log_format &&
1897 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001898 free(defproxy.logformat_string);
1899
1900 free(defproxy.uniqueid_format_string);
1901
Willy Tarreaua534fea2008-08-03 12:19:50 +02001902 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001903 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001904
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 /* we cannot free uri_auth because it might already be used */
1906 init_default_instance();
1907 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001908 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 }
1911 else if (curproxy == NULL) {
1912 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
1916
Willy Tarreau977b8e42006-12-29 14:19:17 +01001917
1918 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001920 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001921 int cur_arg;
1922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 if (curproxy == &defproxy) {
1924 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_ALERT | ERR_FATAL;
1926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930
Emeric Bruned760922010-10-22 17:59:25 +02001931 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001932 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001937
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001938 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001939
1940 /* use default settings for unix sockets */
1941 bind_conf->ux.uid = global.unix_bind.ux.uid;
1942 bind_conf->ux.gid = global.unix_bind.ux.gid;
1943 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001944
1945 /* NOTE: the following line might create several listeners if there
1946 * are comma-separated IPs or port ranges. So all further processing
1947 * will have to be applied to all listeners created after last_listen.
1948 */
Willy Tarreau902636f2013-03-10 19:44:48 +01001949 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
1950 if (errmsg && *errmsg) {
1951 indent_msg(&errmsg, 2);
1952 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001953 }
1954 else
1955 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1956 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
1958 goto out;
1959 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001960
Willy Tarreau4348fad2012-09-20 16:48:07 +02001961 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1962 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001963 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001964 }
1965
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001966 cur_arg = 2;
1967 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001968 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001969 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001970 char *err;
1971
Willy Tarreau26982662012-09-12 23:17:10 +02001972 kw = bind_find_kw(args[cur_arg]);
1973 if (kw) {
1974 char *err = NULL;
1975 int code;
1976
1977 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001978 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1979 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001980 cur_arg += 1 + kw->skip ;
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984
Willy Tarreau4348fad2012-09-20 16:48:07 +02001985 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001986 err_code |= code;
1987
1988 if (code) {
1989 if (err && *err) {
1990 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001991 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001992 }
1993 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001994 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1995 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001996 if (code & ERR_FATAL) {
1997 free(err);
1998 cur_arg += 1 + kw->skip;
1999 goto out;
2000 }
2001 }
2002 free(err);
2003 cur_arg += 1 + kw->skip;
2004 continue;
2005 }
2006
Willy Tarreau8638f482012-09-18 18:01:17 +02002007 err = NULL;
2008 if (!bind_dumped) {
2009 bind_dump_kws(&err);
2010 indent_msg(&err, 4);
2011 bind_dumped = 1;
2012 }
2013
2014 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2015 file, linenum, args[0], args[1], args[cur_arg],
2016 err ? " Registered keywords :" : "", err ? err : "");
2017 free(err);
2018
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002021 }
Willy Tarreau93893792009-07-23 13:19:11 +02002022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 }
2024 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2025 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2026 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002031 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 /* flush useless bits */
2035 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002038 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002040 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041
Willy Tarreau1c47f852006-07-09 08:22:27 +02002042 if (!*args[1]) {
2043 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 }
2048
Willy Tarreaua534fea2008-08-03 12:19:50 +02002049 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002050 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002051 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002052 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002053 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2054
Willy Tarreau93893792009-07-23 13:19:11 +02002055 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2058 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2059 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2060 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2061 else {
2062 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 }
2066 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002067 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002068 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002069
2070 if (curproxy == &defproxy) {
2071 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002075 }
2076
2077 if (!*args[1]) {
2078 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002082 }
2083
2084 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002085 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002086
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002087 if (curproxy->uuid <= 0) {
2088 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002089 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002092 }
2093
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002094 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2095 if (node) {
2096 struct proxy *target = container_of(node, struct proxy, conf.id);
2097 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2098 file, linenum, proxy_type_str(curproxy), curproxy->id,
2099 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
2102 }
2103 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002104 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002105 else if (!strcmp(args[0], "description")) {
2106 int i, len=0;
2107 char *d;
2108
Cyril Bonté99ed3272010-01-24 23:29:44 +01002109 if (curproxy == &defproxy) {
2110 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2111 file, linenum, args[0]);
2112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
2114 }
2115
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002116 if (!*args[1]) {
2117 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2118 file, linenum, args[0]);
2119 return -1;
2120 }
2121
2122 for(i=1; *args[i]; i++)
2123 len += strlen(args[i])+1;
2124
2125 d = (char *)calloc(1, len);
2126 curproxy->desc = d;
2127
2128 d += sprintf(d, "%s", args[1]);
2129 for(i=2; *args[i]; i++)
2130 d += sprintf(d, " %s", args[i]);
2131
2132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2134 curproxy->state = PR_STSTOPPED;
2135 }
2136 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2137 curproxy->state = PR_STNEW;
2138 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002139 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2140 int cur_arg = 1;
2141 unsigned int set = 0;
2142
2143 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002144 unsigned int low, high;
2145
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002146 if (strcmp(args[cur_arg], "all") == 0) {
2147 set = 0;
2148 break;
2149 }
2150 else if (strcmp(args[cur_arg], "odd") == 0) {
2151 set |= 0x55555555;
2152 }
2153 else if (strcmp(args[cur_arg], "even") == 0) {
2154 set |= 0xAAAAAAAA;
2155 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002156 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002157 char *dash = strchr(args[cur_arg], '-');
2158
2159 low = high = str2uic(args[cur_arg]);
2160 if (dash)
2161 high = str2uic(dash + 1);
2162
2163 if (high < low) {
2164 unsigned int swap = low;
2165 low = high;
2166 high = swap;
2167 }
2168
2169 if (low < 1 || high > 32) {
2170 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002171 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002172 err_code |= ERR_ALERT | ERR_FATAL;
2173 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002174 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002175
2176 if (high > global.nbproc) {
2177 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2178 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002179 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002180 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002181 while (low <= high)
2182 set |= 1 << (low++ - 1);
2183 }
2184 else {
2185 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2186 file, linenum, args[0]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002189 }
2190 cur_arg++;
2191 }
2192 curproxy->bind_proc = set;
2193 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002194 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002195 if (curproxy == &defproxy) {
2196 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002199 }
2200
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002201 err = invalid_char(args[1]);
2202 if (err) {
2203 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2204 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002206 }
2207
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002208 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2209 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2210 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002213 }
2214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2216 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002220
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221 if (*(args[1]) == 0) {
2222 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2223 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002227
Willy Tarreau67402132012-05-31 20:40:20 +02002228 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002229 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002230 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002231 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 curproxy->cookie_name = strdup(args[1]);
2233 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002234
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 cur_arg = 2;
2236 while (*(args[cur_arg])) {
2237 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002238 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 }
2240 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002241 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
2243 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002244 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002247 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002250 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002252 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002253 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002256 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002258 else if (!strcmp(args[cur_arg], "httponly")) {
2259 curproxy->ck_opts |= PR_CK_HTTPONLY;
2260 }
2261 else if (!strcmp(args[cur_arg], "secure")) {
2262 curproxy->ck_opts |= PR_CK_SECURE;
2263 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002264 else if (!strcmp(args[cur_arg], "domain")) {
2265 if (!*args[cur_arg + 1]) {
2266 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2267 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002270 }
2271
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002272 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002273 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002274 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2275 " dots nor does not start with a dot."
2276 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002277 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002278 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002279 }
2280
2281 err = invalid_domainchar(args[cur_arg + 1]);
2282 if (err) {
2283 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2284 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002287 }
2288
Willy Tarreau68a897b2009-12-03 23:28:34 +01002289 if (!curproxy->cookie_domain) {
2290 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2291 } else {
2292 /* one domain was already specified, add another one by
2293 * building the string which will be returned along with
2294 * the cookie.
2295 */
2296 char *new_ptr;
2297 int new_len = strlen(curproxy->cookie_domain) +
2298 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2299 new_ptr = malloc(new_len);
2300 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2301 free(curproxy->cookie_domain);
2302 curproxy->cookie_domain = new_ptr;
2303 }
Willy Tarreau31936852010-10-06 16:59:56 +02002304 cur_arg++;
2305 }
2306 else if (!strcmp(args[cur_arg], "maxidle")) {
2307 unsigned int maxidle;
2308 const char *res;
2309
2310 if (!*args[cur_arg + 1]) {
2311 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2312 file, linenum, args[cur_arg]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316
2317 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2318 if (res) {
2319 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2320 file, linenum, *res, args[cur_arg]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324 curproxy->cookie_maxidle = maxidle;
2325 cur_arg++;
2326 }
2327 else if (!strcmp(args[cur_arg], "maxlife")) {
2328 unsigned int maxlife;
2329 const char *res;
2330
2331 if (!*args[cur_arg + 1]) {
2332 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2333 file, linenum, args[cur_arg]);
2334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
2336 }
2337
2338 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2339 if (res) {
2340 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2341 file, linenum, *res, args[cur_arg]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002346 cur_arg++;
2347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002349 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 +02002350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 cur_arg++;
2355 }
Willy Tarreau67402132012-05-31 20:40:20 +02002356 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2358 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
2361
Willy Tarreau67402132012-05-31 20:40:20 +02002362 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2364 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002367
Willy Tarreau67402132012-05-31 20:40:20 +02002368 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002369 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2370 file, linenum);
2371 err_code |= ERR_ALERT | ERR_FATAL;
2372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002374 else if (!strcmp(args[0], "persist")) { /* persist */
2375 if (*(args[1]) == 0) {
2376 Alert("parsing [%s:%d] : missing persist method.\n",
2377 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
2379 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002380 }
2381
2382 if (!strncmp(args[1], "rdp-cookie", 10)) {
2383 curproxy->options2 |= PR_O2_RDPC_PRST;
2384
Emeric Brunb982a3d2010-01-04 15:45:53 +01002385 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002386 const char *beg, *end;
2387
2388 beg = args[1] + 11;
2389 end = strchr(beg, ')');
2390
2391 if (!end || end == beg) {
2392 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2393 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002396 }
2397
2398 free(curproxy->rdp_cookie_name);
2399 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2400 curproxy->rdp_cookie_len = end-beg;
2401 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002402 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002403 free(curproxy->rdp_cookie_name);
2404 curproxy->rdp_cookie_name = strdup("msts");
2405 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2406 }
2407 else { /* syntax */
2408 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2409 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002412 }
2413 }
2414 else {
2415 Alert("parsing [%s:%d] : unknown persist method.\n",
2416 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002419 }
2420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002422 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002424 if (curproxy == &defproxy) {
2425 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002432
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002434 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 }
2439 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002440 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 curproxy->appsession_name = strdup(args[1]);
2442 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2443 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002444 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2445 if (err) {
2446 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2447 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002450 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002451 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002452
Willy Tarreau51041c72007-09-09 21:56:53 +02002453 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2454 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_ABORT;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002458
2459 cur_arg = 6;
2460 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002461 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2462 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002463 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002464 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002465 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002466 } else if (!strcmp(args[cur_arg], "prefix")) {
2467 curproxy->options2 |= PR_O2_AS_PFX;
2468 } else if (!strcmp(args[cur_arg], "mode")) {
2469 if (!*args[cur_arg + 1]) {
2470 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2471 file, linenum, args[0], args[cur_arg]);
2472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
2474 }
2475
2476 cur_arg++;
2477 if (!strcmp(args[cur_arg], "query-string")) {
2478 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2479 curproxy->options2 |= PR_O2_AS_M_QS;
2480 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2481 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2482 curproxy->options2 |= PR_O2_AS_M_PP;
2483 } else {
2484 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002489 cur_arg++;
2490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 } /* Url App Session */
2492 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002493 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002495
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002497 if (curproxy == &defproxy) {
2498 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 if (*(args[4]) == 0) {
2504 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002509 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002510 curproxy->capture_name = strdup(args[2]);
2511 curproxy->capture_namelen = strlen(curproxy->capture_name);
2512 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 curproxy->to_log |= LW_COOKIE;
2514 }
2515 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2516 struct cap_hdr *hdr;
2517
2518 if (curproxy == &defproxy) {
2519 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 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523
2524 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2525 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2526 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530
2531 hdr = calloc(sizeof(struct cap_hdr), 1);
2532 hdr->next = curproxy->req_cap;
2533 hdr->name = strdup(args[3]);
2534 hdr->namelen = strlen(args[3]);
2535 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002536 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 hdr->index = curproxy->nb_req_cap++;
2538 curproxy->req_cap = hdr;
2539 curproxy->to_log |= LW_REQHDR;
2540 }
2541 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2542 struct cap_hdr *hdr;
2543
2544 if (curproxy == &defproxy) {
2545 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 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
2549
2550 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2551 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2552 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 }
2556 hdr = calloc(sizeof(struct cap_hdr), 1);
2557 hdr->next = curproxy->rsp_cap;
2558 hdr->name = strdup(args[3]);
2559 hdr->namelen = strlen(args[3]);
2560 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002561 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 hdr->index = curproxy->nb_rsp_cap++;
2563 curproxy->rsp_cap = hdr;
2564 curproxy->to_log |= LW_RSPHDR;
2565 }
2566 else {
2567 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
2572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002574 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002576
Willy Tarreaubaaee002006-06-26 02:48:02 +02002577 if (*(args[1]) == 0) {
2578 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
2583 curproxy->conn_retries = atol(args[1]);
2584 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002585 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002586 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002587
2588 if (curproxy == &defproxy) {
2589 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
2592 }
2593
Willy Tarreau20b0de52012-12-24 15:45:22 +01002594 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2595 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2596 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2597 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2598 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2599 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 +01002600 file, linenum, args[0]);
2601 err_code |= ERR_WARN;
2602 }
2603
Willy Tarreauff011f22011-01-06 17:51:27 +01002604 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002605
Willy Tarreauff011f22011-01-06 17:51:27 +01002606 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002607 err_code |= ERR_ALERT | ERR_ABORT;
2608 goto out;
2609 }
2610
Willy Tarreauff011f22011-01-06 17:51:27 +01002611 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2612 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002613 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002614 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2615 /* set the header name and length into the proxy structure */
2616 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2617 err_code |= ERR_WARN;
2618
2619 if (!*args[1]) {
2620 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2621 file, linenum, args[0]);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625
2626 /* set the desired header name */
2627 free(curproxy->server_id_hdr_name);
2628 curproxy->server_id_hdr_name = strdup(args[1]);
2629 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2630 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002631 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002632 if (curproxy == &defproxy) {
2633 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002636 }
2637
Willy Tarreauef6494c2010-01-28 17:12:36 +01002638 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002639 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2640 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002643 }
2644
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002645 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2646 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2647 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002650 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002651
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002652 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002653 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002654 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002655 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002656 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002657
Cyril Bonté99ed3272010-01-24 23:29:44 +01002658 if (curproxy == &defproxy) {
2659 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663
Willy Tarreau4baae242012-12-27 12:00:31 +01002664 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2665 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2666 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 }
2670
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002671 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002672 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2673 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002674 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002675 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676 struct switching_rule *rule;
2677
Willy Tarreaub099aca2008-10-12 17:26:37 +02002678 if (curproxy == &defproxy) {
2679 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002682 }
2683
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002686
2687 if (*(args[1]) == 0) {
2688 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691 }
2692
Willy Tarreauef6494c2010-01-28 17:12:36 +01002693 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002694 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2695 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002698 }
2699
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002700 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2701 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2702 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002705 }
2706
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002707 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002708
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2710 rule->cond = cond;
2711 rule->be.name = strdup(args[1]);
2712 LIST_INIT(&rule->list);
2713 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2714 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002715 else if (strcmp(args[0], "use-server") == 0) {
2716 struct server_rule *rule;
2717
2718 if (curproxy == &defproxy) {
2719 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723
2724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2725 err_code |= ERR_WARN;
2726
2727 if (*(args[1]) == 0) {
2728 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
2732
2733 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2734 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2735 file, linenum, args[0]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002740 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2741 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2742 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746
2747 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2748
2749 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2750 rule->cond = cond;
2751 rule->srv.name = strdup(args[1]);
2752 LIST_INIT(&rule->list);
2753 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2754 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2755 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002756 else if ((!strcmp(args[0], "force-persist")) ||
2757 (!strcmp(args[0], "ignore-persist"))) {
2758 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002759
2760 if (curproxy == &defproxy) {
2761 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2767 err_code |= ERR_WARN;
2768
Willy Tarreauef6494c2010-01-28 17:12:36 +01002769 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002770 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2771 file, linenum, args[0]);
2772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
2774 }
2775
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002776 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2777 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2778 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
2781 }
2782
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002783 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002784
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002785 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002786 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002787 if (!strcmp(args[0], "force-persist")) {
2788 rule->type = PERSIST_TYPE_FORCE;
2789 } else {
2790 rule->type = PERSIST_TYPE_IGNORE;
2791 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002792 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002793 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002794 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002795 else if (!strcmp(args[0], "stick-table")) {
2796 int myidx = 1;
2797
Emeric Brun32da3c42010-09-23 18:39:19 +02002798 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002799 curproxy->table.type = (unsigned int)-1;
2800 while (*args[myidx]) {
2801 const char *err;
2802
2803 if (strcmp(args[myidx], "size") == 0) {
2804 myidx++;
2805 if (!*(args[myidx])) {
2806 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2807 file, linenum, args[myidx-1]);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810 }
2811 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2812 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2813 file, linenum, *err, args[myidx-1]);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
2816 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002817 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002818 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002819 else if (strcmp(args[myidx], "peers") == 0) {
2820 myidx++;
2821 if (!*(args[myidx])) {
2822 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2823 file, linenum, args[myidx-1]);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827 curproxy->table.peers.name = strdup(args[myidx++]);
2828 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002829 else if (strcmp(args[myidx], "expire") == 0) {
2830 myidx++;
2831 if (!*(args[myidx])) {
2832 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2833 file, linenum, args[myidx-1]);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
2836 }
2837 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2838 if (err) {
2839 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2840 file, linenum, *err, args[myidx-1]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002845 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 }
2847 else if (strcmp(args[myidx], "nopurge") == 0) {
2848 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002849 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002850 }
2851 else if (strcmp(args[myidx], "type") == 0) {
2852 myidx++;
2853 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2854 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2855 file, linenum, args[myidx]);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002859 /* myidx already points to next arg */
2860 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002861 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002862 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002863 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002864
2865 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002866 nw = args[myidx];
2867 while (*nw) {
2868 /* the "store" keyword supports a comma-separated list */
2869 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002870 sa = NULL; /* store arg */
2871 while (*nw && *nw != ',') {
2872 if (*nw == '(') {
2873 *nw = 0;
2874 sa = ++nw;
2875 while (*nw != ')') {
2876 if (!*nw) {
2877 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2878 file, linenum, args[0], cw);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 nw++;
2883 }
2884 *nw = '\0';
2885 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002886 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002887 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002888 if (*nw)
2889 *nw++ = '\0';
2890 type = stktable_get_data_type(cw);
2891 if (type < 0) {
2892 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2893 file, linenum, args[0], cw);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
Willy Tarreauac782882010-06-20 10:41:54 +02002897
2898 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2899 switch (err) {
2900 case PE_NONE: break;
2901 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002902 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2903 file, linenum, args[0], cw);
2904 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002905 break;
2906
2907 case PE_ARG_MISSING:
2908 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2909 file, linenum, args[0], cw);
2910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912
2913 case PE_ARG_NOT_USED:
2914 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2915 file, linenum, args[0], cw);
2916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918
2919 default:
2920 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2921 file, linenum, args[0], cw);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002924 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002925 }
2926 myidx++;
2927 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002928 else {
2929 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2930 file, linenum, args[myidx]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 }
2935
2936 if (!curproxy->table.size) {
2937 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2938 file, linenum);
2939 err_code |= ERR_ALERT | ERR_FATAL;
2940 goto out;
2941 }
2942
2943 if (curproxy->table.type == (unsigned int)-1) {
2944 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2945 file, linenum);
2946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
2948 }
2949 }
2950 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002951 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002952 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 int myidx = 0;
2954 const char *name = NULL;
2955 int flags;
2956
2957 if (curproxy == &defproxy) {
2958 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2959 err_code |= ERR_ALERT | ERR_FATAL;
2960 goto out;
2961 }
2962
2963 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2964 err_code |= ERR_WARN;
2965 goto out;
2966 }
2967
2968 myidx++;
2969 if ((strcmp(args[myidx], "store") == 0) ||
2970 (strcmp(args[myidx], "store-request") == 0)) {
2971 myidx++;
2972 flags = STK_IS_STORE;
2973 }
2974 else if (strcmp(args[myidx], "store-response") == 0) {
2975 myidx++;
2976 flags = STK_IS_STORE | STK_ON_RSP;
2977 }
2978 else if (strcmp(args[myidx], "match") == 0) {
2979 myidx++;
2980 flags = STK_IS_MATCH;
2981 }
2982 else if (strcmp(args[myidx], "on") == 0) {
2983 myidx++;
2984 flags = STK_IS_MATCH | STK_IS_STORE;
2985 }
2986 else {
2987 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991
2992 if (*(args[myidx]) == 0) {
2993 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002998 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002999 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003000 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
3003 }
3004
3005 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003006 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003007 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3008 file, linenum, args[0], expr->fetch->kw);
3009 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003010 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003011 goto out;
3012 }
3013 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003014 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003015 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3016 file, linenum, args[0], expr->fetch->kw);
3017 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003018 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 goto out;
3020 }
3021 }
3022
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003023 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3024 if (expr->fetch->cap & SMP_CAP_L7)
3025 curproxy->acl_requires |= ACL_USE_L7_ANY;
3026
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 if (strcmp(args[myidx], "table") == 0) {
3028 myidx++;
3029 name = args[myidx++];
3030 }
3031
Willy Tarreauef6494c2010-01-28 17:12:36 +01003032 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003033 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3034 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3035 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003037 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 goto out;
3039 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003041 else if (*(args[myidx])) {
3042 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3043 file, linenum, args[0], args[myidx]);
3044 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003045 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003046 goto out;
3047 }
Emeric Brun97679e72010-09-23 17:56:44 +02003048 if (flags & STK_ON_RSP)
3049 err_code |= warnif_cond_requires_req(cond, file, linenum);
3050 else
3051 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003052
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3054 rule->cond = cond;
3055 rule->expr = expr;
3056 rule->flags = flags;
3057 rule->table.name = name ? strdup(name) : NULL;
3058 LIST_INIT(&rule->list);
3059 if (flags & STK_ON_RSP)
3060 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3061 else
3062 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003067
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3069 curproxy->uri_auth = NULL; /* we must detach from the default config */
3070
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003071 if (!*args[1]) {
3072 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003073 } else if (!strcmp(args[1], "admin")) {
3074 struct stats_admin_rule *rule;
3075
3076 if (curproxy == &defproxy) {
3077 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
3080 }
3081
3082 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3083 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
3086 }
3087
3088 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3089 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3090 file, linenum, args[0], args[1]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003094 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3095 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3096 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3102
3103 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3104 rule->cond = cond;
3105 LIST_INIT(&rule->list);
3106 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 } else if (!strcmp(args[1], "uri")) {
3108 if (*(args[2]) == 0) {
3109 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3113 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_ABORT;
3115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 }
3117 } else if (!strcmp(args[1], "realm")) {
3118 if (*(args[2]) == 0) {
3119 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003127 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003128 unsigned interval;
3129
3130 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3131 if (err) {
3132 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3133 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_FATAL;
3135 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003136 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3137 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003138 err_code |= ERR_ALERT | ERR_ABORT;
3139 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003140 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003141 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003142 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003143
3144 if (curproxy == &defproxy) {
3145 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
3150 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
3154 }
3155
Willy Tarreauff011f22011-01-06 17:51:27 +01003156 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3157 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003158 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3159 file, linenum, args[0]);
3160 err_code |= ERR_WARN;
3161 }
3162
Willy Tarreauff011f22011-01-06 17:51:27 +01003163 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003164
Willy Tarreauff011f22011-01-06 17:51:27 +01003165 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003166 err_code |= ERR_ALERT | ERR_ABORT;
3167 goto out;
3168 }
3169
Willy Tarreauff011f22011-01-06 17:51:27 +01003170 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3171 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003172
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 } else if (!strcmp(args[1], "auth")) {
3174 if (*(args[2]) == 0) {
3175 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3179 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003180 err_code |= ERR_ALERT | ERR_ABORT;
3181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003182 }
3183 } else if (!strcmp(args[1], "scope")) {
3184 if (*(args[2]) == 0) {
3185 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3189 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_ABORT;
3191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
3193 } else if (!strcmp(args[1], "enable")) {
3194 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3195 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003199 } else if (!strcmp(args[1], "hide-version")) {
3200 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3201 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003202 err_code |= ERR_ALERT | ERR_ABORT;
3203 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003204 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003205 } else if (!strcmp(args[1], "show-legends")) {
3206 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3207 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3208 err_code |= ERR_ALERT | ERR_ABORT;
3209 goto out;
3210 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003211 } else if (!strcmp(args[1], "show-node")) {
3212
3213 if (*args[2]) {
3214 int i;
3215 char c;
3216
3217 for (i=0; args[2][i]; i++) {
3218 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003219 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3220 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003221 break;
3222 }
3223
3224 if (!i || args[2][i]) {
3225 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3226 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3227 file, linenum, args[0], args[1]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
3231 }
3232
3233 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3234 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3235 err_code |= ERR_ALERT | ERR_ABORT;
3236 goto out;
3237 }
3238 } else if (!strcmp(args[1], "show-desc")) {
3239 char *desc = NULL;
3240
3241 if (*args[2]) {
3242 int i, len=0;
3243 char *d;
3244
3245 for(i=2; *args[i]; i++)
3246 len += strlen(args[i])+1;
3247
3248 desc = d = (char *)calloc(1, len);
3249
3250 d += sprintf(d, "%s", args[2]);
3251 for(i=3; *args[i]; i++)
3252 d += sprintf(d, " %s", args[i]);
3253 }
3254
3255 if (!*args[2] && !global.desc)
3256 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3257 file, linenum, args[1]);
3258 else {
3259 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3260 free(desc);
3261 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3262 err_code |= ERR_ALERT | ERR_ABORT;
3263 goto out;
3264 }
3265 free(desc);
3266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003268stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003269 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 +01003270 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 }
3274 }
3275 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003276 int optnum;
3277
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003278 if (*(args[1]) == '\0') {
3279 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003284
3285 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3286 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003287 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3288 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3289 file, linenum, cfg_opts[optnum].name);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
Willy Tarreau93893792009-07-23 13:19:11 +02003293 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3294 err_code |= ERR_WARN;
3295 goto out;
3296 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003297
Willy Tarreau3842f002009-06-14 11:39:52 +02003298 curproxy->no_options &= ~cfg_opts[optnum].val;
3299 curproxy->options &= ~cfg_opts[optnum].val;
3300
3301 switch (kwm) {
3302 case KWM_STD:
3303 curproxy->options |= cfg_opts[optnum].val;
3304 break;
3305 case KWM_NO:
3306 curproxy->no_options |= cfg_opts[optnum].val;
3307 break;
3308 case KWM_DEF: /* already cleared */
3309 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003310 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003311
Willy Tarreau93893792009-07-23 13:19:11 +02003312 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003313 }
3314 }
3315
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003316 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3317 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003318 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3319 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3320 file, linenum, cfg_opts2[optnum].name);
3321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
3323 }
Willy Tarreau93893792009-07-23 13:19:11 +02003324 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3325 err_code |= ERR_WARN;
3326 goto out;
3327 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003328
Willy Tarreau3842f002009-06-14 11:39:52 +02003329 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3330 curproxy->options2 &= ~cfg_opts2[optnum].val;
3331
3332 switch (kwm) {
3333 case KWM_STD:
3334 curproxy->options2 |= cfg_opts2[optnum].val;
3335 break;
3336 case KWM_NO:
3337 curproxy->no_options2 |= cfg_opts2[optnum].val;
3338 break;
3339 case KWM_DEF: /* already cleared */
3340 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003341 }
Willy Tarreau93893792009-07-23 13:19:11 +02003342 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003343 }
3344 }
3345
Willy Tarreau3842f002009-06-14 11:39:52 +02003346 if (kwm != KWM_STD) {
3347 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003348 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003351 }
3352
Emeric Brun3a058f32009-06-30 18:26:00 +02003353 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003354 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003356 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003357 if (*(args[2]) != '\0') {
3358 if (!strcmp(args[2], "clf")) {
3359 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003360 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003361 } else {
3362 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003365 }
3366 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003367 if (curproxy->logformat_string != default_http_log_format &&
3368 curproxy->logformat_string != default_tcp_log_format &&
3369 curproxy->logformat_string != clf_http_log_format)
3370 free(curproxy->logformat_string);
3371 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003372 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003373 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003375 if (curproxy->logformat_string != default_http_log_format &&
3376 curproxy->logformat_string != default_tcp_log_format &&
3377 curproxy->logformat_string != clf_http_log_format)
3378 free(curproxy->logformat_string);
3379 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003380 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 else if (!strcmp(args[1], "tcpka")) {
3382 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003383 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003385
3386 if (curproxy->cap & PR_CAP_FE)
3387 curproxy->options |= PR_O_TCP_CLI_KA;
3388 if (curproxy->cap & PR_CAP_BE)
3389 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
3391 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003392 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_WARN;
3394
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003396 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003397 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003398 curproxy->options2 &= ~PR_O2_CHK_ANY;
3399 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 if (!*args[2]) { /* no argument */
3401 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3402 curproxy->check_len = strlen(DEF_CHECK_REQ);
3403 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003404 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 curproxy->check_req = (char *)malloc(reqlen);
3406 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003407 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003409 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 if (*args[4])
3411 reqlen += strlen(args[4]);
3412 else
3413 reqlen += strlen("HTTP/1.0");
3414
3415 curproxy->check_req = (char *)malloc(reqlen);
3416 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003417 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003419 }
3420 else if (!strcmp(args[1], "ssl-hello-chk")) {
3421 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003424
Willy Tarreaua534fea2008-08-03 12:19:50 +02003425 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003426 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003427 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003428 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
Willy Tarreau23677902007-05-08 23:50:35 +02003430 else if (!strcmp(args[1], "smtpchk")) {
3431 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003432 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003433 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003434 curproxy->options2 &= ~PR_O2_CHK_ANY;
3435 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003436
3437 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3438 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3439 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3440 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3441 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3442 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3443 curproxy->check_req = (char *)malloc(reqlen);
3444 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3445 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3446 } else {
3447 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3448 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3449 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3450 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3451 }
3452 }
3453 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003454 else if (!strcmp(args[1], "lb-agent-chk")) {
3455 /* use dynmaic health check */
3456 free(curproxy->check_req);
3457 curproxy->check_req = NULL;
3458 curproxy->options2 &= ~PR_O2_CHK_ANY;
3459 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3460 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003461 else if (!strcmp(args[1], "pgsql-check")) {
3462 /* use PostgreSQL request to check servers' health */
3463 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3464 err_code |= ERR_WARN;
3465
3466 free(curproxy->check_req);
3467 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003468 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003469 curproxy->options2 |= PR_O2_PGSQL_CHK;
3470
3471 if (*(args[2])) {
3472 int cur_arg = 2;
3473
3474 while (*(args[cur_arg])) {
3475 if (strcmp(args[cur_arg], "user") == 0) {
3476 char * packet;
3477 uint32_t packet_len;
3478 uint32_t pv;
3479
3480 /* suboption header - needs additional argument for it */
3481 if (*(args[cur_arg+1]) == 0) {
3482 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3483 file, linenum, args[0], args[1], args[cur_arg]);
3484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
3486 }
3487
3488 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3489 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3490 pv = htonl(0x30000); /* protocol version 3.0 */
3491
3492 packet = (char*) calloc(1, packet_len);
3493
3494 memcpy(packet + 4, &pv, 4);
3495
3496 /* copy "user" */
3497 memcpy(packet + 8, "user", 4);
3498
3499 /* copy username */
3500 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3501
3502 free(curproxy->check_req);
3503 curproxy->check_req = packet;
3504 curproxy->check_len = packet_len;
3505
3506 packet_len = htonl(packet_len);
3507 memcpy(packet, &packet_len, 4);
3508 cur_arg += 2;
3509 } else {
3510 /* unknown suboption - catchall */
3511 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3512 file, linenum, args[0], args[1]);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
3516 } /* end while loop */
3517 }
3518 }
3519
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003520 else if (!strcmp(args[1], "redis-check")) {
3521 /* use REDIS PING request to check servers' health */
3522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3523 err_code |= ERR_WARN;
3524
3525 free(curproxy->check_req);
3526 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003527 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003528 curproxy->options2 |= PR_O2_REDIS_CHK;
3529
3530 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3531 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3532 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3533 }
3534
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003535 else if (!strcmp(args[1], "mysql-check")) {
3536 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3538 err_code |= ERR_WARN;
3539
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003540 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003541 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003542 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003543 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003544
3545 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3546 * const char mysql40_client_auth_pkt[] = {
3547 * "\x0e\x00\x00" // packet length
3548 * "\x01" // packet number
3549 * "\x00\x00" // client capabilities
3550 * "\x00\x00\x01" // max packet
3551 * "haproxy\x00" // username (null terminated string)
3552 * "\x00" // filler (always 0x00)
3553 * "\x01\x00\x00" // packet length
3554 * "\x00" // packet number
3555 * "\x01" // COM_QUIT command
3556 * };
3557 */
3558
3559 if (*(args[2])) {
3560 int cur_arg = 2;
3561
3562 while (*(args[cur_arg])) {
3563 if (strcmp(args[cur_arg], "user") == 0) {
3564 char *mysqluser;
3565 int packetlen, reqlen, userlen;
3566
3567 /* suboption header - needs additional argument for it */
3568 if (*(args[cur_arg+1]) == 0) {
3569 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3570 file, linenum, args[0], args[1], args[cur_arg]);
3571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
3573 }
3574 mysqluser = args[cur_arg + 1];
3575 userlen = strlen(mysqluser);
3576 packetlen = userlen + 7;
3577 reqlen = packetlen + 9;
3578
3579 free(curproxy->check_req);
3580 curproxy->check_req = (char *)calloc(1, reqlen);
3581 curproxy->check_len = reqlen;
3582
3583 snprintf(curproxy->check_req, 4, "%c%c%c",
3584 ((unsigned char) packetlen & 0xff),
3585 ((unsigned char) (packetlen >> 8) & 0xff),
3586 ((unsigned char) (packetlen >> 16) & 0xff));
3587
3588 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003589 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003590 curproxy->check_req[8] = 1;
3591 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3592 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3593 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3594 cur_arg += 2;
3595 } else {
3596 /* unknown suboption - catchall */
3597 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3598 file, linenum, args[0], args[1]);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601 }
3602 } /* end while loop */
3603 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003604 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003605 else if (!strcmp(args[1], "ldap-check")) {
3606 /* use LDAP request to check servers' health */
3607 free(curproxy->check_req);
3608 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003609 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003610 curproxy->options2 |= PR_O2_LDAP_CHK;
3611
3612 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3613 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3614 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3615 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003616 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003617 int cur_arg;
3618
3619 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3620 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003621 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003622
Willy Tarreau87cf5142011-08-19 22:57:24 +02003623 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003624
3625 free(curproxy->fwdfor_hdr_name);
3626 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3627 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3628
3629 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3630 cur_arg = 2;
3631 while (*(args[cur_arg])) {
3632 if (!strcmp(args[cur_arg], "except")) {
3633 /* suboption except - needs additional argument for it */
3634 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3635 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3636 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003639 }
3640 /* flush useless bits */
3641 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003642 cur_arg += 2;
3643 } else if (!strcmp(args[cur_arg], "header")) {
3644 /* suboption header - needs additional argument for it */
3645 if (*(args[cur_arg+1]) == 0) {
3646 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3647 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003650 }
3651 free(curproxy->fwdfor_hdr_name);
3652 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3653 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3654 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003655 } else if (!strcmp(args[cur_arg], "if-none")) {
3656 curproxy->options &= ~PR_O_FF_ALWAYS;
3657 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003658 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003659 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003660 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003661 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003664 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003666 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003667 else if (!strcmp(args[1], "originalto")) {
3668 int cur_arg;
3669
3670 /* insert x-original-to field, but not for the IP address listed as an except.
3671 * set default options (ie: bitfield, header name, etc)
3672 */
3673
3674 curproxy->options |= PR_O_ORGTO;
3675
3676 free(curproxy->orgto_hdr_name);
3677 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3678 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3679
Willy Tarreau87cf5142011-08-19 22:57:24 +02003680 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003681 cur_arg = 2;
3682 while (*(args[cur_arg])) {
3683 if (!strcmp(args[cur_arg], "except")) {
3684 /* suboption except - needs additional argument for it */
3685 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3686 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3687 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003690 }
3691 /* flush useless bits */
3692 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3693 cur_arg += 2;
3694 } else if (!strcmp(args[cur_arg], "header")) {
3695 /* suboption header - needs additional argument for it */
3696 if (*(args[cur_arg+1]) == 0) {
3697 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3698 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003701 }
3702 free(curproxy->orgto_hdr_name);
3703 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3704 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3705 cur_arg += 2;
3706 } else {
3707 /* unknown suboption - catchall */
3708 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3709 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003712 }
3713 } /* end while loop */
3714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 else {
3716 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
Willy Tarreau93893792009-07-23 13:19:11 +02003720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003722 else if (!strcmp(args[0], "default_backend")) {
3723 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003725
3726 if (*(args[1]) == 0) {
3727 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003730 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003731 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003732 curproxy->defbe.name = strdup(args[1]);
3733 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003734 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003737
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003738 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 /* enable reconnections to dispatch */
3742 curproxy->options |= PR_O_REDISP;
3743 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003744 else if (!strcmp(args[0], "http-check")) {
3745 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003747
3748 if (strcmp(args[1], "disable-on-404") == 0) {
3749 /* enable a graceful server shutdown on an HTTP 404 response */
3750 curproxy->options |= PR_O_DISABLE404;
3751 }
Willy Tarreauef781042010-01-27 11:53:01 +01003752 else if (strcmp(args[1], "send-state") == 0) {
3753 /* enable emission of the apparent state of a server in HTTP checks */
3754 curproxy->options2 |= PR_O2_CHK_SNDST;
3755 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003756 else if (strcmp(args[1], "expect") == 0) {
3757 const char *ptr_arg;
3758 int cur_arg;
3759
3760 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3761 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765
3766 cur_arg = 2;
3767 /* consider exclamation marks, sole or at the beginning of a word */
3768 while (*(ptr_arg = args[cur_arg])) {
3769 while (*ptr_arg == '!') {
3770 curproxy->options2 ^= PR_O2_EXP_INV;
3771 ptr_arg++;
3772 }
3773 if (*ptr_arg)
3774 break;
3775 cur_arg++;
3776 }
3777 /* now ptr_arg points to the beginning of a word past any possible
3778 * exclamation mark, and cur_arg is the argument which holds this word.
3779 */
3780 if (strcmp(ptr_arg, "status") == 0) {
3781 if (!*(args[cur_arg + 1])) {
3782 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3783 file, linenum, args[0], args[1], ptr_arg);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
3787 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003788 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003789 curproxy->expect_str = strdup(args[cur_arg + 1]);
3790 }
3791 else if (strcmp(ptr_arg, "string") == 0) {
3792 if (!*(args[cur_arg + 1])) {
3793 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3794 file, linenum, args[0], args[1], ptr_arg);
3795 err_code |= ERR_ALERT | ERR_FATAL;
3796 goto out;
3797 }
3798 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003799 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003800 curproxy->expect_str = strdup(args[cur_arg + 1]);
3801 }
3802 else if (strcmp(ptr_arg, "rstatus") == 0) {
3803 if (!*(args[cur_arg + 1])) {
3804 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3805 file, linenum, args[0], args[1], ptr_arg);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003810 free(curproxy->expect_str);
3811 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3812 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003813 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3814 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3815 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3816 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
3819 }
3820 }
3821 else if (strcmp(ptr_arg, "rstring") == 0) {
3822 if (!*(args[cur_arg + 1])) {
3823 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3824 file, linenum, args[0], args[1], ptr_arg);
3825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
3827 }
3828 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003829 free(curproxy->expect_str);
3830 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3831 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003832 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3833 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3834 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3835 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 }
3840 else {
3841 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3842 file, linenum, args[0], args[1], ptr_arg);
3843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
3845 }
3846 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003847 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003848 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 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003851 }
3852 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003853 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003858 }
3859
Willy Tarreaub80c2302007-11-30 20:51:32 +01003860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862
3863 if (strcmp(args[1], "fail") == 0) {
3864 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003865 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3867 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003868 err_code |= ERR_ALERT | ERR_FATAL;
3869 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003870 }
3871
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003872 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3873 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3874 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003877 }
3878 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3879 }
3880 else {
3881 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003884 }
3885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886#ifdef TPROXY
3887 else if (!strcmp(args[0], "transparent")) {
3888 /* enable transparent proxy connections */
3889 curproxy->options |= PR_O_TRANSP;
3890 }
3891#endif
3892 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003893 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 if (*(args[1]) == 0) {
3897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
3901 curproxy->maxconn = atol(args[1]);
3902 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003903 else if (!strcmp(args[0], "backlog")) { /* backlog */
3904 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003906
3907 if (*(args[1]) == 0) {
3908 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003911 }
3912 curproxy->backlog = atol(args[1]);
3913 }
Willy Tarreau86034312006-12-29 00:10:33 +01003914 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003917
Willy Tarreau86034312006-12-29 00:10:33 +01003918 if (*(args[1]) == 0) {
3919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003922 }
3923 curproxy->fullconn = atol(args[1]);
3924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3926 if (*(args[1]) == 0) {
3927 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003931 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3932 if (err) {
3933 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3934 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003937 }
3938 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003941 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003942 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003943 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003944
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 if (curproxy == &defproxy) {
3946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003950 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952
Willy Tarreau902636f2013-03-10 19:44:48 +01003953 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003954 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01003955 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003956 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003957 goto out;
3958 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003959
3960 proto = protocol_by_family(sk->ss_family);
3961 if (!proto || !proto->connect) {
3962 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3963 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967
3968 if (port1 != port2) {
3969 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3970 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003974
3975 if (!port1) {
3976 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3977 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003981
Willy Tarreaud5191e72010-02-09 20:50:45 +01003982 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003983 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984 }
3985 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003988
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003989 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3990 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003991 err_code |= ERR_ALERT | ERR_FATAL;
3992 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003995 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3997 err_code |= ERR_WARN;
3998
3999 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4000 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4001 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4002 }
4003 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4004 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4005 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4006 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004007 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4008 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4009 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4010 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004011 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004012 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 }
4016 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 short realport = 0;
4020 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004027 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004028 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029
4030 if (!*args[2]) {
4031 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4032 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004036
4037 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004038 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004039 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4040 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004043 }
4044
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004045 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004046 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004047 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004048 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004049
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004050 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4051 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4052 err_code |= ERR_ALERT | ERR_ABORT;
4053 goto out;
4054 }
4055
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004056 /* the servers are linked backwards first */
4057 newsrv->next = curproxy->srv;
4058 curproxy->srv = newsrv;
4059 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004060 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004061 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004063 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004064 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004065 LIST_INIT(&newsrv->pendconns);
4066 do_check = 0;
4067 newsrv->state = SRV_RUNNING; /* early server setup */
4068 newsrv->last_change = now.tv_sec;
4069 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004072 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004073 * - IP: => port=+0, relative
4074 * - IP:N => port=N, absolute
4075 * - IP:+N => port=+N, relative
4076 * - IP:-N => port=-N, relative
4077 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004078 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004079 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004080 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004081 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004082 goto out;
4083 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004084
4085 proto = protocol_by_family(sk->ss_family);
4086 if (!proto || !proto->connect) {
4087 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4088 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004092
4093 if (!port1 || !port2) {
4094 /* no port specified, +offset, -offset */
4095 newsrv->state |= SRV_MAPPORTS;
4096 }
4097 else if (port1 != port2) {
4098 /* port range */
4099 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4100 file, linenum, args[0], args[1], args[2]);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
4104 else {
4105 /* used by checks */
4106 realport = port1;
4107 }
4108
Willy Tarreaud5191e72010-02-09 20:50:45 +01004109 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004110 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4111 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004112
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004113 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004114 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4115 file, linenum, newsrv->addr.ss_family, args[2]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004119
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004120 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004121 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 newsrv->inter = curproxy->defsrv.inter;
4123 newsrv->fastinter = curproxy->defsrv.fastinter;
4124 newsrv->downinter = curproxy->defsrv.downinter;
4125 newsrv->rise = curproxy->defsrv.rise;
4126 newsrv->fall = curproxy->defsrv.fall;
4127 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4128 newsrv->minconn = curproxy->defsrv.minconn;
4129 newsrv->maxconn = curproxy->defsrv.maxconn;
4130 newsrv->slowstart = curproxy->defsrv.slowstart;
4131 newsrv->onerror = curproxy->defsrv.onerror;
4132 newsrv->consecutive_errors_limit
4133 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004134#ifdef OPENSSL
4135 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4136#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004137 newsrv->uweight = newsrv->iweight
4138 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004140 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004142 cur_arg = 3;
4143 } else {
4144 newsrv = &curproxy->defsrv;
4145 cur_arg = 1;
4146 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004147
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004149 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 newsrv->cookie = strdup(args[cur_arg + 1]);
4151 newsrv->cklen = strlen(args[cur_arg + 1]);
4152 cur_arg += 2;
4153 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004154 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004155 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4156 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4157 cur_arg += 2;
4158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004159 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004160 if (!*args[cur_arg + 1]) {
4161 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4162 file, linenum, args[cur_arg]);
4163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
4165 }
4166
Willy Tarreaubaaee002006-06-26 02:48:02 +02004167 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004168 if (newsrv->rise <= 0) {
4169 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4170 file, linenum, args[cur_arg]);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174
Willy Tarreau96839092010-03-29 10:02:24 +02004175 if (newsrv->health)
4176 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 cur_arg += 2;
4178 }
4179 else if (!strcmp(args[cur_arg], "fall")) {
4180 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004181
4182 if (!*args[cur_arg + 1]) {
4183 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4184 file, linenum, args[cur_arg]);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187 }
4188
4189 if (newsrv->fall <= 0) {
4190 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4191 file, linenum, args[cur_arg]);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
4195
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 cur_arg += 2;
4197 }
4198 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004199 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4200 if (err) {
4201 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4202 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004205 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004206 if (val <= 0) {
4207 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4208 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004211 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004212 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 cur_arg += 2;
4214 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004215 else if (!strcmp(args[cur_arg], "fastinter")) {
4216 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4217 if (err) {
4218 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4219 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004222 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004223 if (val <= 0) {
4224 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4225 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004228 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004229 newsrv->fastinter = val;
4230 cur_arg += 2;
4231 }
4232 else if (!strcmp(args[cur_arg], "downinter")) {
4233 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4234 if (err) {
4235 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4236 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004239 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004240 if (val <= 0) {
4241 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4242 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004245 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004246 newsrv->downinter = val;
4247 cur_arg += 2;
4248 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004249 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004250 struct sockaddr_storage *sk;
4251 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004252 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004253
Willy Tarreau902636f2013-03-10 19:44:48 +01004254 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004255 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004256 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004257 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004258 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004259 goto out;
4260 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004261
4262 proto = protocol_by_family(sk->ss_family);
4263 if (!proto || !proto->connect) {
4264 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004265 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004269
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004270 if (port1 != port2) {
4271 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4272 file, linenum, args[cur_arg], args[cur_arg + 1]);
4273 err_code |= ERR_ALERT | ERR_FATAL;
4274 goto out;
4275 }
4276
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004277 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004278 cur_arg += 2;
4279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004281 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 cur_arg += 2;
4283 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004284 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 newsrv->state |= SRV_BACKUP;
4286 cur_arg ++;
4287 }
Simon Hormanfa461682011-06-25 09:39:49 +09004288 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4289 newsrv->state |= SRV_NON_STICK;
4290 cur_arg ++;
4291 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004292 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4293 newsrv->state |= SRV_SEND_PROXY;
4294 cur_arg ++;
4295 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004296 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4297 newsrv->check.send_proxy = 1;
4298 cur_arg ++;
4299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 else if (!strcmp(args[cur_arg], "weight")) {
4301 int w;
4302 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004303 if (w < 0 || w > 256) {
4304 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004309 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004310 cur_arg += 2;
4311 }
4312 else if (!strcmp(args[cur_arg], "minconn")) {
4313 newsrv->minconn = atol(args[cur_arg + 1]);
4314 cur_arg += 2;
4315 }
4316 else if (!strcmp(args[cur_arg], "maxconn")) {
4317 newsrv->maxconn = atol(args[cur_arg + 1]);
4318 cur_arg += 2;
4319 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004320 else if (!strcmp(args[cur_arg], "maxqueue")) {
4321 newsrv->maxqueue = atol(args[cur_arg + 1]);
4322 cur_arg += 2;
4323 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004324 else if (!strcmp(args[cur_arg], "slowstart")) {
4325 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004326 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004327 if (err) {
4328 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4329 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004332 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004333 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004334 cur_arg += 2;
4335 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004336 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004337
4338 if (!*args[cur_arg + 1]) {
4339 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4340 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004343 }
4344
4345 newsrv->trackit = strdup(args[cur_arg + 1]);
4346
4347 cur_arg += 2;
4348 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004349 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004350 global.maxsock++;
4351 do_check = 1;
4352 cur_arg += 1;
4353 }
Willy Tarreau96839092010-03-29 10:02:24 +02004354 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4355 newsrv->state |= SRV_MAINTAIN;
4356 newsrv->state &= ~SRV_RUNNING;
4357 newsrv->health = 0;
4358 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004359 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004360 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004361 if (!strcmp(args[cur_arg + 1], "none"))
4362 newsrv->observe = HANA_OBS_NONE;
4363 else if (!strcmp(args[cur_arg + 1], "layer4"))
4364 newsrv->observe = HANA_OBS_LAYER4;
4365 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4366 if (curproxy->mode != PR_MODE_HTTP) {
4367 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4368 file, linenum, args[cur_arg + 1]);
4369 err_code |= ERR_ALERT;
4370 }
4371 newsrv->observe = HANA_OBS_LAYER7;
4372 }
4373 else {
4374 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004375 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004376 file, linenum, args[cur_arg], args[cur_arg + 1]);
4377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
4379 }
4380
4381 cur_arg += 2;
4382 }
4383 else if (!strcmp(args[cur_arg], "on-error")) {
4384 if (!strcmp(args[cur_arg + 1], "fastinter"))
4385 newsrv->onerror = HANA_ONERR_FASTINTER;
4386 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4387 newsrv->onerror = HANA_ONERR_FAILCHK;
4388 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4389 newsrv->onerror = HANA_ONERR_SUDDTH;
4390 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4391 newsrv->onerror = HANA_ONERR_MARKDWN;
4392 else {
4393 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004394 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004395 file, linenum, args[cur_arg], args[cur_arg + 1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 cur_arg += 2;
4401 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004402 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4403 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4404 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4405 else {
4406 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4407 file, linenum, args[cur_arg], args[cur_arg + 1]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411
4412 cur_arg += 2;
4413 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004414 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4415 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4416 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4417 else {
4418 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4419 file, linenum, args[cur_arg], args[cur_arg + 1]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423
4424 cur_arg += 2;
4425 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004426 else if (!strcmp(args[cur_arg], "error-limit")) {
4427 if (!*args[cur_arg + 1]) {
4428 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4429 file, linenum, args[cur_arg]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433
4434 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4435
4436 if (newsrv->consecutive_errors_limit <= 0) {
4437 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4438 file, linenum, args[cur_arg]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004442 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004443 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004444 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004445 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004446 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004447 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004448
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004450 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4451 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004455
Willy Tarreauef9a3602012-12-08 22:29:20 +01004456 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004457 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004458 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004459 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004460 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004462 goto out;
4463 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004464
4465 proto = protocol_by_family(sk->ss_family);
4466 if (!proto || !proto->connect) {
4467 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4468 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004472
Willy Tarreauef9a3602012-12-08 22:29:20 +01004473 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004474
4475 if (port_low != port_high) {
4476 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004477
4478 if (!port_low || !port_high) {
4479 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4480 file, linenum, args[cur_arg], args[cur_arg + 1]);
4481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
4483 }
4484
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004485 if (port_low <= 0 || port_low > 65535 ||
4486 port_high <= 0 || port_high > 65535 ||
4487 port_low > port_high) {
4488 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4489 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004492 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004493 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4494 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4495 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004496 }
4497
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004499 while (*(args[cur_arg])) {
4500 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004501#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4502#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004503 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004504 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4505 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004508 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004509#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004510 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004511 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004512 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004515 }
4516 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004517 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4518 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004520 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4521 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004522 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4523 char *name, *end;
4524
4525 name = args[cur_arg+1] + 7;
4526 while (isspace(*name))
4527 name++;
4528
4529 end = name;
4530 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4531 end++;
4532
Willy Tarreauef9a3602012-12-08 22:29:20 +01004533 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4534 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4535 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4536 newsrv->conn_src.bind_hdr_len = end - name;
4537 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4538 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4539 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004540
4541 /* now look for an occurrence number */
4542 while (isspace(*end))
4543 end++;
4544 if (*end == ',') {
4545 end++;
4546 name = end;
4547 if (*end == '-')
4548 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004549 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004550 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004551 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004552 }
4553
Willy Tarreauef9a3602012-12-08 22:29:20 +01004554 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004555 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4556 " occurrences values smaller than %d.\n",
4557 file, linenum, MAX_HDR_HISTORY);
4558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
4560 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004561 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004562 struct sockaddr_storage *sk;
4563 int port1, port2;
4564
Willy Tarreau902636f2013-03-10 19:44:48 +01004565 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004566 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004567 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004568 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004569 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004570 goto out;
4571 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004572
4573 proto = protocol_by_family(sk->ss_family);
4574 if (!proto || !proto->connect) {
4575 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4576 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004580
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004581 if (port1 != port2) {
4582 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4583 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
4586 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004587 newsrv->conn_src.tproxy_addr = *sk;
4588 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004589 }
4590 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004591#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004592 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004593#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004594 cur_arg += 2;
4595 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004596#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004597 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004598 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004601#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4602 } /* "usesrc" */
4603
4604 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4605#ifdef SO_BINDTODEVICE
4606 if (!*args[cur_arg + 1]) {
4607 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004609 err_code |= ERR_ALERT | ERR_FATAL;
4610 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004611 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004612 free(newsrv->conn_src.iface_name);
4613 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4614 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004615 global.last_checks |= LSTCHK_NETADM;
4616#else
4617 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4618 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004621#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004622 cur_arg += 2;
4623 continue;
4624 }
4625 /* this keyword in not an option of "source" */
4626 break;
4627 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004630 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4631 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004636 static int srv_dumped;
4637 struct srv_kw *kw;
4638 char *err;
4639
4640 kw = srv_find_kw(args[cur_arg]);
4641 if (kw) {
4642 char *err = NULL;
4643 int code;
4644
4645 if (!kw->parse) {
4646 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4647 file, linenum, args[0], args[1], args[cur_arg]);
4648 cur_arg += 1 + kw->skip ;
4649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
4651 }
4652
4653 if (defsrv && !kw->default_ok) {
4654 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4655 file, linenum, args[0], args[1], args[cur_arg]);
4656 cur_arg += 1 + kw->skip ;
4657 err_code |= ERR_ALERT;
4658 continue;
4659 }
4660
4661 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4662 err_code |= code;
4663
4664 if (code) {
4665 if (err && *err) {
4666 indent_msg(&err, 2);
4667 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4668 }
4669 else
4670 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4671 file, linenum, args[0], args[1], args[cur_arg]);
4672 if (code & ERR_FATAL) {
4673 free(err);
4674 cur_arg += 1 + kw->skip;
4675 goto out;
4676 }
4677 }
4678 free(err);
4679 cur_arg += 1 + kw->skip;
4680 continue;
4681 }
4682
4683 err = NULL;
4684 if (!srv_dumped) {
4685 srv_dump_kws(&err);
4686 indent_msg(&err, 4);
4687 srv_dumped = 1;
4688 }
4689
4690 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4691 file, linenum, args[0], args[1], args[cur_arg],
4692 err ? " Registered keywords :" : "", err ? err : "");
4693 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004694
Willy Tarreau93893792009-07-23 13:19:11 +02004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 }
4698 }
4699
4700 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004701 if (newsrv->trackit) {
4702 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4703 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004706 }
4707
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004708 /* If neither a port nor an addr was specified and no check transport
4709 * layer is forced, then the transport layer used by the checks is the
4710 * same as for the production traffic. Otherwise we use raw_sock by
4711 * default, unless one is specified.
4712 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004713 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004714#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004715 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004716#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004717 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4718 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004719 /* try to get the port from check.addr if check.port not set */
4720 if (!newsrv->check.port)
4721 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004722
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004723 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004724 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004725
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004726 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004727 /* not yet valid, because no port was set on
4728 * the server either. We'll check if we have
4729 * a known port on the first listener.
4730 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004731 struct listener *l;
4732
4733 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004734 newsrv->check.port = get_host_port(&l->addr);
4735 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004736 break;
4737 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004738 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004739 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4741 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004745
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004746 /* Allocate buffer for check requests... */
4747 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004748 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4749 err_code |= ERR_ALERT | ERR_ABORT;
4750 goto out;
4751 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004752 newsrv->check.bi->size = global.tune.chksize;
4753
4754 /* Allocate buffer for check responses... */
4755 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4756 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4757 err_code |= ERR_ALERT | ERR_ABORT;
4758 goto out;
4759 }
4760 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004761
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004762 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004763 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004764 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4765 err_code |= ERR_ALERT | ERR_ABORT;
4766 goto out;
4767 }
4768
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004769 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4770 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 newsrv->state |= SRV_CHECKED;
4772 }
4773
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004774 if (!defsrv) {
4775 if (newsrv->state & SRV_BACKUP)
4776 curproxy->srv_bck++;
4777 else
4778 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004779
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004780 newsrv->prev_state = newsrv->state;
4781 }
William Lallemanda73203e2012-03-12 12:48:57 +01004782 }
4783
4784 else if (strcmp(args[0], "unique-id-format") == 0) {
4785 if (!*(args[1])) {
4786 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
William Lallemand3203ff42012-11-11 17:30:56 +01004790 if (*(args[2])) {
4791 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004795 free(curproxy->uniqueid_format_string);
4796 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004797 }
William Lallemanda73203e2012-03-12 12:48:57 +01004798
4799 else if (strcmp(args[0], "unique-id-header") == 0) {
4800 if (!*(args[1])) {
4801 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
4804 }
4805 free(curproxy->header_unique_id);
4806 curproxy->header_unique_id = strdup(args[1]);
4807 }
4808
William Lallemand723b73a2012-02-08 16:37:49 +01004809 else if (strcmp(args[0], "log-format") == 0) {
4810 if (!*(args[1])) {
4811 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
4814 }
William Lallemand3203ff42012-11-11 17:30:56 +01004815 if (*(args[2])) {
4816 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004820
4821 if (curproxy->logformat_string != default_http_log_format &&
4822 curproxy->logformat_string != default_tcp_log_format &&
4823 curproxy->logformat_string != clf_http_log_format)
4824 free(curproxy->logformat_string);
4825 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
William Lallemand723b73a2012-02-08 16:37:49 +01004827
William Lallemand0f99e342011-10-12 17:50:54 +02004828 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4829 /* delete previous herited or defined syslog servers */
4830 struct logsrv *back;
4831
4832 if (*(args[1]) != 0) {
4833 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
4836 }
4837
William Lallemand723b73a2012-02-08 16:37:49 +01004838 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4839 LIST_DEL(&tmplogsrv->list);
4840 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004841 }
4842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004844 struct logsrv *logsrv;
4845
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004847 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004848 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004849 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004850 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004851 LIST_INIT(&node->list);
4852 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4853 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
4855 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004856 struct sockaddr_storage *sk;
4857 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02004858
4859 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860
William Lallemand0f99e342011-10-12 17:50:54 +02004861 logsrv->facility = get_log_facility(args[2]);
4862 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
4866
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 }
4868
William Lallemand0f99e342011-10-12 17:50:54 +02004869 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004871 logsrv->level = get_log_level(args[3]);
4872 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
4876
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
4878 }
4879
William Lallemand0f99e342011-10-12 17:50:54 +02004880 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004881 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004882 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004883 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004884 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004888 }
4889 }
4890
Willy Tarreau902636f2013-03-10 19:44:48 +01004891 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004892 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004893 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004894 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004895 goto out;
4896 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004897
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004898 logsrv->addr = *sk;
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 Tarreau2de5dae2013-03-10 18:51:54 +01004925 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004926
Willy Tarreau977b8e42006-12-29 14:19:17 +01004927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004929
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004931 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4932 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004936
4937 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004938 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4939 free(curproxy->conn_src.iface_name);
4940 curproxy->conn_src.iface_name = NULL;
4941 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004942
Willy Tarreau902636f2013-03-10 19:44:48 +01004943 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004944 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004945 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004946 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004947 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004948 goto out;
4949 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004950
4951 proto = protocol_by_family(sk->ss_family);
4952 if (!proto || !proto->connect) {
4953 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004954 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958
4959 if (port1 != port2) {
4960 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4961 file, linenum, args[0], args[1]);
4962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
4964 }
4965
Willy Tarreauef9a3602012-12-08 22:29:20 +01004966 curproxy->conn_src.source_addr = *sk;
4967 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004968
4969 cur_arg = 2;
4970 while (*(args[cur_arg])) {
4971 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004972#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4973#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004974 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004975 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4976 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004979 }
4980#endif
4981 if (!*args[cur_arg + 1]) {
4982 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4983 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004986 }
4987
4988 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004989 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4990 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004991 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004992 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4993 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004994 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4995 char *name, *end;
4996
4997 name = args[cur_arg+1] + 7;
4998 while (isspace(*name))
4999 name++;
5000
5001 end = name;
5002 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5003 end++;
5004
Willy Tarreauef9a3602012-12-08 22:29:20 +01005005 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5006 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5007 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5008 curproxy->conn_src.bind_hdr_len = end - name;
5009 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5010 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5011 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005012
5013 /* now look for an occurrence number */
5014 while (isspace(*end))
5015 end++;
5016 if (*end == ',') {
5017 end++;
5018 name = end;
5019 if (*end == '-')
5020 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005021 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005022 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005023 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005024 }
5025
Willy Tarreauef9a3602012-12-08 22:29:20 +01005026 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005027 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5028 " occurrences values smaller than %d.\n",
5029 file, linenum, MAX_HDR_HISTORY);
5030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
5032 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005033 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005034 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005035
Willy Tarreau902636f2013-03-10 19:44:48 +01005036 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005037 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005038 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005039 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005040 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005041 goto out;
5042 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005043
5044 proto = protocol_by_family(sk->ss_family);
5045 if (!proto || !proto->connect) {
5046 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5047 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
5050 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005051
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005052 if (port1 != port2) {
5053 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5054 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005058 curproxy->conn_src.tproxy_addr = *sk;
5059 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005060 }
5061 global.last_checks |= LSTCHK_NETADM;
5062#if !defined(CONFIG_HAP_LINUX_TPROXY)
5063 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005064#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065#else /* no TPROXY support */
5066 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005067 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005070#endif
5071 cur_arg += 2;
5072 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005073 }
5074
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005075 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5076#ifdef SO_BINDTODEVICE
5077 if (!*args[cur_arg + 1]) {
5078 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005082 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005083 free(curproxy->conn_src.iface_name);
5084 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5085 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005086 global.last_checks |= LSTCHK_NETADM;
5087#else
5088 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5089 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005092#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005093 cur_arg += 2;
5094 continue;
5095 }
5096 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005097 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005102 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5103 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5104 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115
5116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005117 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005118 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
5122 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005124 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 }
5129 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005131 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005132 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
5136 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005138 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005139 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
5143 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005145 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005146 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005149 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005150 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005152 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005153 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005155 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005156 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005157 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005158 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005159 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005160 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005162 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005163 }
5164 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005165 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005166 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005167 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005169 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005172 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178
5179 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005180 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005181 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
5185 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005187 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005188 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005194 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
5199 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005201 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005202 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005207 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005208 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005209 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005213 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005215 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005216 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005218 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005221 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005222
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 if (curproxy == &defproxy) {
5224 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005228 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005229 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 if (*(args[1]) == 0) {
5232 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005236
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005237 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005238 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5239 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5240 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
5244 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5245 }
5246 else if (*args[2]) {
5247 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5248 file, linenum, args[0], args[2]);
5249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
5251 }
5252
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005253 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005254 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005255 wl->s = strdup(args[1]);
5256 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005257 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005266
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005269 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 }
5280 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005283 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 }
5287 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005288 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5290 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
5294
Willy Tarreauade5ec42010-01-28 19:33:49 +01005295 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005296 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005297 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005298 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
5301 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005302 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005303 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005304 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005305 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 }
5308 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005309 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005310 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005311 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005312 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 }
5315 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005316 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005317
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 if (curproxy == &defproxy) {
5319 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005323 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 if (*(args[1]) == 0) {
5327 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
5331
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005332 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005333 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5334 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5335 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339 err_code |= warnif_cond_requires_req(cond, file, linenum);
5340 }
5341 else if (*args[2]) {
5342 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5343 file, linenum, args[0], args[2]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005348 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005349 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005350 wl->s = strdup(args[1]);
5351 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 }
5353 else if (!strcmp(args[0], "errorloc") ||
5354 !strcmp(args[0], "errorloc302") ||
5355 !strcmp(args[0], "errorloc303")) { /* error location */
5356 int errnum, errlen;
5357 char *err;
5358
Willy Tarreau977b8e42006-12-29 14:19:17 +01005359 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005360 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005361
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005363 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 }
5367
5368 errnum = atol(args[1]);
5369 if (!strcmp(args[0], "errorloc303")) {
5370 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5371 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5372 } else {
5373 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5374 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5375 }
5376
Willy Tarreau0f772532006-12-23 20:51:41 +01005377 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5378 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005379 chunk_destroy(&curproxy->errmsg[rc]);
5380 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005381 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005384
5385 if (rc >= HTTP_ERR_SIZE) {
5386 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5387 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 free(err);
5389 }
5390 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005391 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5392 int errnum, errlen, fd;
5393 char *err;
5394 struct stat stat;
5395
5396 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005397 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005398
5399 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005400 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005403 }
5404
5405 fd = open(args[2], O_RDONLY);
5406 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5407 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5408 file, linenum, args[2], args[1]);
5409 if (fd >= 0)
5410 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005413 }
5414
Willy Tarreau27a674e2009-08-17 07:23:33 +02005415 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005416 errlen = stat.st_size;
5417 } else {
5418 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005419 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005420 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005421 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005422 }
5423
5424 err = malloc(errlen); /* malloc() must succeed during parsing */
5425 errnum = read(fd, err, errlen);
5426 if (errnum != errlen) {
5427 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5428 file, linenum, args[2], args[1]);
5429 close(fd);
5430 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005433 }
5434 close(fd);
5435
5436 errnum = atol(args[1]);
5437 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5438 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005439 chunk_destroy(&curproxy->errmsg[rc]);
5440 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005441 break;
5442 }
5443 }
5444
5445 if (rc >= HTTP_ERR_SIZE) {
5446 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5447 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005449 free(err);
5450 }
5451 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005452 else if (!strcmp(args[0], "compression")) {
5453 struct comp *comp;
5454 if (curproxy->comp == NULL) {
5455 comp = calloc(1, sizeof(struct comp));
5456 curproxy->comp = comp;
5457 } else {
5458 comp = curproxy->comp;
5459 }
5460
5461 if (!strcmp(args[1], "algo")) {
5462 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005463 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005464
William Lallemand82fe75c2012-10-23 10:25:10 +02005465 cur_arg = 2;
5466 if (!*args[cur_arg]) {
5467 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5468 file, linenum, args[0]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472 while (*(args[cur_arg])) {
5473 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5474 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5475 file, linenum, args[0], args[cur_arg]);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
William Lallemand552df672012-11-07 13:21:47 +01005479 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5480 curproxy->comp->algos->end(&ctx);
5481 } else {
5482 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5483 file, linenum, args[0], args[cur_arg]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005487 cur_arg ++;
5488 continue;
5489 }
5490 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005491 else if (!strcmp(args[1], "offload")) {
5492 comp->offload = 1;
5493 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005494 else if (!strcmp(args[1], "type")) {
5495 int cur_arg;
5496 cur_arg = 2;
5497 if (!*args[cur_arg]) {
5498 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5499 file, linenum, args[0]);
5500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 while (*(args[cur_arg])) {
5504 comp_append_type(comp, args[cur_arg]);
5505 cur_arg ++;
5506 continue;
5507 }
5508 }
5509 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005510 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005511 file, linenum, args[0]);
5512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
5514 }
5515 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005517 struct cfg_kw_list *kwl;
5518 int index;
5519
5520 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5521 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5522 if (kwl->kw[index].section != CFG_LISTEN)
5523 continue;
5524 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5525 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005526 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005527 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005528 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005531 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005532 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005533 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005534 err_code |= ERR_WARN;
5535 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005536 }
Willy Tarreau93893792009-07-23 13:19:11 +02005537 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005538 }
5539 }
5540 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005541
Willy Tarreau6daf3432008-01-22 16:44:08 +01005542 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
Willy Tarreau93893792009-07-23 13:19:11 +02005546 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005547 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549}
5550
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005551int
5552cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5553{
5554
5555 int err_code = 0;
5556 const char *err;
5557
5558 if (!strcmp(args[0], "userlist")) { /* new userlist */
5559 struct userlist *newul;
5560
5561 if (!*args[1]) {
5562 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5563 file, linenum, args[0]);
5564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567
5568 err = invalid_char(args[1]);
5569 if (err) {
5570 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5571 file, linenum, *err, args[0], args[1]);
5572 err_code |= ERR_ALERT | ERR_FATAL;
5573 goto out;
5574 }
5575
5576 for (newul = userlist; newul; newul = newul->next)
5577 if (!strcmp(newul->name, args[1])) {
5578 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5579 file, linenum, args[1]);
5580 err_code |= ERR_WARN;
5581 goto out;
5582 }
5583
5584 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5585 if (!newul) {
5586 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5587 err_code |= ERR_ALERT | ERR_ABORT;
5588 goto out;
5589 }
5590
5591 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5592 newul->name = strdup(args[1]);
5593
5594 if (!newul->groupusers | !newul->name) {
5595 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5596 err_code |= ERR_ALERT | ERR_ABORT;
5597 goto out;
5598 }
5599
5600 newul->next = userlist;
5601 userlist = newul;
5602
5603 } else if (!strcmp(args[0], "group")) { /* new group */
5604 int cur_arg, i;
5605 const char *err;
5606
5607 if (!*args[1]) {
5608 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5609 file, linenum, args[0]);
5610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
5613
5614 err = invalid_char(args[1]);
5615 if (err) {
5616 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5617 file, linenum, *err, args[0], args[1]);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
5621
5622 for(i = 0; i < userlist->grpcnt; i++)
5623 if (!strcmp(userlist->groups[i], args[1])) {
5624 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5625 file, linenum, args[1], userlist->name);
5626 err_code |= ERR_ALERT;
5627 goto out;
5628 }
5629
5630 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5631 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5632 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
5635 }
5636
5637 cur_arg = 2;
5638
5639 while (*args[cur_arg]) {
5640 if (!strcmp(args[cur_arg], "users")) {
5641 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5642 cur_arg += 2;
5643 continue;
5644 } else {
5645 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5646 file, linenum, args[0]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650 }
5651
5652 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5653 } else if (!strcmp(args[0], "user")) { /* new user */
5654 struct auth_users *newuser;
5655 int cur_arg;
5656
5657 if (!*args[1]) {
5658 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5659 file, linenum, args[0]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663
5664 for (newuser = userlist->users; newuser; newuser = newuser->next)
5665 if (!strcmp(newuser->user, args[1])) {
5666 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5667 file, linenum, args[1], userlist->name);
5668 err_code |= ERR_ALERT;
5669 goto out;
5670 }
5671
5672 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5673 if (!newuser) {
5674 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5675 err_code |= ERR_ALERT | ERR_ABORT;
5676 goto out;
5677 }
5678
5679 newuser->user = strdup(args[1]);
5680
5681 newuser->next = userlist->users;
5682 userlist->users = newuser;
5683
5684 cur_arg = 2;
5685
5686 while (*args[cur_arg]) {
5687 if (!strcmp(args[cur_arg], "password")) {
5688#ifndef CONFIG_HAP_CRYPT
5689 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5690 file, linenum);
5691 err_code |= ERR_ALERT;
5692#endif
5693 newuser->pass = strdup(args[cur_arg + 1]);
5694 cur_arg += 2;
5695 continue;
5696 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5697 newuser->pass = strdup(args[cur_arg + 1]);
5698 newuser->flags |= AU_O_INSECURE;
5699 cur_arg += 2;
5700 continue;
5701 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005702 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005703 cur_arg += 2;
5704 continue;
5705 } else {
5706 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5707 file, linenum, args[0]);
5708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
5710 }
5711 }
5712 } else {
5713 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5714 err_code |= ERR_ALERT | ERR_FATAL;
5715 }
5716
5717out:
5718 return err_code;
5719}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720
5721/*
5722 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005723 * Returns the error code, 0 if OK, or any combination of :
5724 * - ERR_ABORT: must abort ASAP
5725 * - ERR_FATAL: we can continue parsing but not start the service
5726 * - ERR_WARN: a warning has been emitted
5727 * - ERR_ALERT: an alert has been emitted
5728 * Only the two first ones can stop processing, the two others are just
5729 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005731int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005733 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 FILE *f;
5735 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005737 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739 if ((f=fopen(file,"r")) == NULL)
5740 return -1;
5741
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005742 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005743 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005744 char *end;
5745 char *args[MAX_LINE_ARGS + 1];
5746 char *line = thisline;
5747
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 linenum++;
5749
5750 end = line + strlen(line);
5751
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005752 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5753 /* Check if we reached the limit and the last char is not \n.
5754 * Watch out for the last line without the terminating '\n'!
5755 */
5756 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005757 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005758 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005759 }
5760
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005762 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 line++;
5764
5765 arg = 0;
5766 args[arg] = line;
5767
5768 while (*line && arg < MAX_LINE_ARGS) {
5769 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5770 * C equivalent value. Other combinations left unchanged (eg: \1).
5771 */
5772 if (*line == '\\') {
5773 int skip = 0;
5774 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5775 *line = line[1];
5776 skip = 1;
5777 }
5778 else if (line[1] == 'r') {
5779 *line = '\r';
5780 skip = 1;
5781 }
5782 else if (line[1] == 'n') {
5783 *line = '\n';
5784 skip = 1;
5785 }
5786 else if (line[1] == 't') {
5787 *line = '\t';
5788 skip = 1;
5789 }
5790 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005791 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 unsigned char hex1, hex2;
5793 hex1 = toupper(line[2]) - '0';
5794 hex2 = toupper(line[3]) - '0';
5795 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5796 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5797 *line = (hex1<<4) + hex2;
5798 skip = 3;
5799 }
5800 else {
5801 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005802 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 }
5804 }
5805 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005806 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 end -= skip;
5808 }
5809 line++;
5810 }
5811 else if (*line == '#' || *line == '\n' || *line == '\r') {
5812 /* end of string, end of loop */
5813 *line = 0;
5814 break;
5815 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005816 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005818 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005819 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 line++;
5821 args[++arg] = line;
5822 }
5823 else {
5824 line++;
5825 }
5826 }
5827
5828 /* empty line */
5829 if (!**args)
5830 continue;
5831
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005832 if (*line) {
5833 /* we had to stop due to too many args.
5834 * Let's terminate the string, print the offending part then cut the
5835 * last arg.
5836 */
5837 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5838 line++;
5839 *line = '\0';
5840
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005841 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005842 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 args[arg] = line;
5845 }
5846
Willy Tarreau540abe42007-05-02 20:50:16 +02005847 /* zero out remaining args and ensure that at least one entry
5848 * is zeroed out.
5849 */
5850 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 args[arg] = line;
5852 }
5853
Willy Tarreau3842f002009-06-14 11:39:52 +02005854 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005855 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005856 char *tmp;
5857
Willy Tarreau3842f002009-06-14 11:39:52 +02005858 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005859 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005860 for (arg=0; *args[arg+1]; arg++)
5861 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005862 *tmp = '\0'; // fix the next arg to \0
5863 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005864 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005865 else if (!strcmp(args[0], "default")) {
5866 kwm = KWM_DEF;
5867 for (arg=0; *args[arg+1]; arg++)
5868 args[arg] = args[arg+1]; // shift args after inversion
5869 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005870
William Lallemand0f99e342011-10-12 17:50:54 +02005871 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5872 strcmp(args[0], "log") != 0) {
5873 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005874 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005875 }
5876
Willy Tarreau977b8e42006-12-29 14:19:17 +01005877 if (!strcmp(args[0], "listen") ||
5878 !strcmp(args[0], "frontend") ||
5879 !strcmp(args[0], "backend") ||
5880 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005881 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005883 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005884 cursection = strdup(args[0]);
5885 }
5886 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005888 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005889 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005890 }
5891 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005892 confsect = CFG_USERLIST;
5893 free(cursection);
5894 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005895 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005896 else if (!strcmp(args[0], "peers")) {
5897 confsect = CFG_PEERS;
5898 free(cursection);
5899 cursection = strdup(args[0]);
5900 }
5901
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 /* else it's a section keyword */
5903
5904 switch (confsect) {
5905 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005906 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 break;
5908 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005909 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005911 case CFG_USERLIST:
5912 err_code |= cfg_parse_users(file, linenum, args, kwm);
5913 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005914 case CFG_PEERS:
5915 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5916 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005918 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005919 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005921
5922 if (err_code & ERR_ABORT)
5923 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005925 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005926 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005927 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005928 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005929}
5930
Willy Tarreaubb925012009-07-23 13:36:36 +02005931/*
5932 * Returns the error code, 0 if OK, or any combination of :
5933 * - ERR_ABORT: must abort ASAP
5934 * - ERR_FATAL: we can continue parsing but not start the service
5935 * - ERR_WARN: a warning has been emitted
5936 * - ERR_ALERT: an alert has been emitted
5937 * Only the two first ones can stop processing, the two others are just
5938 * indicators.
5939 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005940int check_config_validity()
5941{
5942 int cfgerr = 0;
5943 struct proxy *curproxy = NULL;
5944 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005945 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005946 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005947 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005948 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005950 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 /*
5952 * Now, check for the integrity of all that we have collected.
5953 */
5954
5955 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005956 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005957
Willy Tarreau193b8c62012-11-22 00:17:38 +01005958 if (!global.tune.max_http_hdr)
5959 global.tune.max_http_hdr = MAX_HTTP_HDR;
5960
5961 if (!global.tune.cookie_len)
5962 global.tune.cookie_len = CAPTURE_LEN;
5963
5964 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5965
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005966 /* first, we will invert the proxy list order */
5967 curproxy = NULL;
5968 while (proxy) {
5969 struct proxy *next;
5970
5971 next = proxy->next;
5972 proxy->next = curproxy;
5973 curproxy = proxy;
5974 if (!next)
5975 break;
5976 proxy = next;
5977 }
5978
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005980 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005981 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005982 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005983 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005984 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005985 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005986 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005987
Willy Tarreau050536d2012-10-04 08:47:34 +02005988 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005989 /* proxy ID not set, use automatic numbering with first
5990 * spare entry starting with next_pxid.
5991 */
5992 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5993 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5994 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005995 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005996 next_pxid++;
5997
Willy Tarreau55ea7572007-06-17 19:56:27 +02005998
Willy Tarreaubaaee002006-06-26 02:48:02 +02005999 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006000 /* ensure we don't keep listeners uselessly bound */
6001 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002 curproxy = curproxy->next;
6003 continue;
6004 }
6005
Willy Tarreau16a21472012-11-19 12:39:59 +01006006 /* number of processes this proxy is bound to */
6007 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6008
Willy Tarreauff01a212009-03-15 13:46:16 +01006009 switch (curproxy->mode) {
6010 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006011 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006012 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6014 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006015 cfgerr++;
6016 }
6017
6018 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006019 Warning("config : servers will be ignored for %s '%s'.\n",
6020 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006021 break;
6022
6023 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006024 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006025 break;
6026
6027 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006028 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006029 break;
6030 }
6031
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006032 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006033 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006034 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006035 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6036 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006037 cfgerr++;
6038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006040 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006041 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6042 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006043 cfgerr++;
6044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006046 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006047 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6048 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006049 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006050 }
6051 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006052 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006053 /* If no LB algo is set in a backend, and we're not in
6054 * transparent mode, dispatch mode nor proxy mode, we
6055 * want to use balance roundrobin by default.
6056 */
6057 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6058 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 }
6060 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006061
Willy Tarreau1620ec32011-08-06 17:05:02 +02006062 if (curproxy->options & PR_O_DISPATCH)
6063 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6064 else if (curproxy->options & PR_O_HTTP_PROXY)
6065 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6066 else if (curproxy->options & PR_O_TRANSP)
6067 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006068
Willy Tarreau1620ec32011-08-06 17:05:02 +02006069 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6070 if (curproxy->options & PR_O_DISABLE404) {
6071 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6072 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6073 err_code |= ERR_WARN;
6074 curproxy->options &= ~PR_O_DISABLE404;
6075 }
6076 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6077 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6078 "send-state", proxy_type_str(curproxy), curproxy->id);
6079 err_code |= ERR_WARN;
6080 curproxy->options &= ~PR_O2_CHK_SNDST;
6081 }
Willy Tarreauef781042010-01-27 11:53:01 +01006082 }
6083
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006084 /* if a default backend was specified, let's find it */
6085 if (curproxy->defbe.name) {
6086 struct proxy *target;
6087
Alex Williams96532db2009-11-01 21:27:13 -05006088 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006089 if (!target) {
6090 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6091 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006092 cfgerr++;
6093 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006094 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6095 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006096 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006097 } else {
6098 free(curproxy->defbe.name);
6099 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006100 /* we force the backend to be present on at least all of
6101 * the frontend's processes.
6102 */
6103 target->bind_proc = curproxy->bind_proc ?
6104 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006105
6106 /* Emit a warning if this proxy also has some servers */
6107 if (curproxy->srv) {
6108 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6109 curproxy->id);
6110 err_code |= ERR_WARN;
6111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 }
6113 }
6114
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006115 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006116 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6117 /* map jump target for ACT_SETBE in req_rep chain */
6118 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006119 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006120 struct proxy *target;
6121
Willy Tarreaua496b602006-12-17 23:15:24 +01006122 if (exp->action != ACT_SETBE)
6123 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006124
Alex Williams96532db2009-11-01 21:27:13 -05006125 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006126 if (!target) {
6127 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6128 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006129 cfgerr++;
6130 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006131 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6132 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006133 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006134 } else {
6135 free((void *)exp->replace);
6136 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006137 /* we force the backend to be present on at least all of
6138 * the frontend's processes.
6139 */
6140 target->bind_proc = curproxy->bind_proc ?
6141 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006142 }
6143 }
6144 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006145
6146 /* find the target proxy for 'use_backend' rules */
6147 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006148 struct proxy *target;
6149
Alex Williams96532db2009-11-01 21:27:13 -05006150 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006151
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006152 if (!target) {
6153 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6154 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006155 cfgerr++;
6156 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006157 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6158 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006159 cfgerr++;
6160 } else {
6161 free((void *)rule->be.name);
6162 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006163 /* we force the backend to be present on at least all of
6164 * the frontend's processes.
6165 */
6166 target->bind_proc = curproxy->bind_proc ?
6167 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006168 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006169 }
6170
6171 /* find the target proxy for 'use_backend' rules */
6172 list_for_each_entry(srule, &curproxy->server_rules, list) {
6173 struct server *target = findserver(curproxy, srule->srv.name);
6174
6175 if (!target) {
6176 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6177 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6178 cfgerr++;
6179 continue;
6180 }
6181 free((void *)srule->srv.name);
6182 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006183 }
6184
Emeric Brunb982a3d2010-01-04 15:45:53 +01006185 /* find the target table for 'stick' rules */
6186 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6187 struct proxy *target;
6188
Emeric Brun1d33b292010-01-04 15:47:17 +01006189 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6190 if (mrule->flags & STK_IS_STORE)
6191 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6192
Emeric Brunb982a3d2010-01-04 15:45:53 +01006193 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006194 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006195 else
6196 target = curproxy;
6197
6198 if (!target) {
6199 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6200 curproxy->id, mrule->table.name);
6201 cfgerr++;
6202 }
6203 else if (target->table.size == 0) {
6204 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6205 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6206 cfgerr++;
6207 }
Willy Tarreau12785782012-04-27 21:37:17 +02006208 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6209 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006210 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6211 cfgerr++;
6212 }
6213 else {
6214 free((void *)mrule->table.name);
6215 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006216 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006217 }
6218 }
6219
6220 /* find the target table for 'store response' rules */
6221 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6222 struct proxy *target;
6223
Emeric Brun1d33b292010-01-04 15:47:17 +01006224 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6225
Emeric Brunb982a3d2010-01-04 15:45:53 +01006226 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006227 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006228 else
6229 target = curproxy;
6230
6231 if (!target) {
6232 Alert("Proxy '%s': unable to find store table '%s'.\n",
6233 curproxy->id, mrule->table.name);
6234 cfgerr++;
6235 }
6236 else if (target->table.size == 0) {
6237 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6238 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6239 cfgerr++;
6240 }
Willy Tarreau12785782012-04-27 21:37:17 +02006241 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6242 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006243 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6244 cfgerr++;
6245 }
6246 else {
6247 free((void *)mrule->table.name);
6248 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006249 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006250 }
6251 }
6252
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006253 /* find the target table for 'tcp-request' layer 4 rules */
6254 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6255 struct proxy *target;
6256
Willy Tarreau56123282010-08-06 19:06:56 +02006257 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006258 continue;
6259
6260 if (trule->act_prm.trk_ctr.table.n)
6261 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6262 else
6263 target = curproxy;
6264
6265 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006266 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6267 curproxy->id, trule->act_prm.trk_ctr.table.n,
6268 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006269 cfgerr++;
6270 }
6271 else if (target->table.size == 0) {
6272 Alert("Proxy '%s': table '%s' used but not configured.\n",
6273 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6274 cfgerr++;
6275 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006276 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6277 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6278 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6279 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6280 cfgerr++;
6281 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006282 else {
6283 free(trule->act_prm.trk_ctr.table.n);
6284 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006285 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006286 * to pass a list of counters to track and allocate them right here using
6287 * stktable_alloc_data_type().
6288 */
6289 }
6290 }
6291
Willy Tarreaud1f96522010-08-03 19:34:32 +02006292 /* find the target table for 'tcp-request' layer 6 rules */
6293 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6294 struct proxy *target;
6295
Willy Tarreau56123282010-08-06 19:06:56 +02006296 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006297 continue;
6298
6299 if (trule->act_prm.trk_ctr.table.n)
6300 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6301 else
6302 target = curproxy;
6303
6304 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006305 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6306 curproxy->id, trule->act_prm.trk_ctr.table.n,
6307 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006308 cfgerr++;
6309 }
6310 else if (target->table.size == 0) {
6311 Alert("Proxy '%s': table '%s' used but not configured.\n",
6312 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6313 cfgerr++;
6314 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006315 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6316 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6317 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6318 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6319 cfgerr++;
6320 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006321 else {
6322 free(trule->act_prm.trk_ctr.table.n);
6323 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006324 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006325 * to pass a list of counters to track and allocate them right here using
6326 * stktable_alloc_data_type().
6327 */
6328 }
6329 }
6330
Emeric Brun32da3c42010-09-23 18:39:19 +02006331 if (curproxy->table.peers.name) {
6332 struct peers *curpeers = peers;
6333
6334 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6335 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6336 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006337 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006338 break;
6339 }
6340 }
6341
6342 if (!curpeers) {
6343 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6344 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006345 free((void *)curproxy->table.peers.name);
6346 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006347 cfgerr++;
6348 }
6349 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006350 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6351 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006352 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006353 cfgerr++;
6354 }
6355 }
6356
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006357 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006358 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006359 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6360 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6361 "proxy", curproxy->id);
6362 cfgerr++;
6363 goto out_uri_auth_compat;
6364 }
6365
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006366 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006367 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006368 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006369 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006370
Willy Tarreau95fa4692010-02-01 13:05:50 +01006371 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6372 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006373
6374 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006375 uri_auth_compat_req[i++] = "realm";
6376 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6377 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006378
Willy Tarreau95fa4692010-02-01 13:05:50 +01006379 uri_auth_compat_req[i++] = "unless";
6380 uri_auth_compat_req[i++] = "{";
6381 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6382 uri_auth_compat_req[i++] = "}";
6383 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006384
Willy Tarreauff011f22011-01-06 17:51:27 +01006385 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6386 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006387 cfgerr++;
6388 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006389 }
6390
Willy Tarreauff011f22011-01-06 17:51:27 +01006391 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006392
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006393 if (curproxy->uri_auth->auth_realm) {
6394 free(curproxy->uri_auth->auth_realm);
6395 curproxy->uri_auth->auth_realm = NULL;
6396 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006397
6398 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006399 }
6400out_uri_auth_compat:
6401
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006402 cfgerr += acl_find_targets(curproxy);
6403
Willy Tarreau2738a142006-07-08 17:28:09 +02006404 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006405 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006406 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006407 (!curproxy->timeout.connect ||
6408 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006409 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006410 " | While not properly invalid, you will certainly encounter various problems\n"
6411 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006412 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006413 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006414 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006415 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006416
Willy Tarreau1fa31262007-12-03 00:36:16 +01006417 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6418 * We must still support older configurations, so let's find out whether those
6419 * parameters have been set or must be copied from contimeouts.
6420 */
6421 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006422 if (!curproxy->timeout.tarpit ||
6423 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006424 /* tarpit timeout not set. We search in the following order:
6425 * default.tarpit, curr.connect, default.connect.
6426 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006427 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006428 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006429 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006430 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006431 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006432 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006433 }
6434 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006435 (!curproxy->timeout.queue ||
6436 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006437 /* queue timeout not set. We search in the following order:
6438 * default.queue, curr.connect, default.connect.
6439 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006440 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006441 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006442 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006443 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006444 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006445 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006446 }
6447 }
6448
Willy Tarreau1620ec32011-08-06 17:05:02 +02006449 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006450 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6451 curproxy->check_req = (char *)malloc(curproxy->check_len);
6452 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006453 }
6454
Willy Tarreau193b8c62012-11-22 00:17:38 +01006455 /* ensure that cookie capture length is not too large */
6456 if (curproxy->capture_len >= global.tune.cookie_len) {
6457 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6458 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6459 err_code |= ERR_WARN;
6460 curproxy->capture_len = global.tune.cookie_len - 1;
6461 }
6462
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006463 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006464 if (curproxy->nb_req_cap) {
6465 if (curproxy->mode == PR_MODE_HTTP) {
6466 curproxy->req_cap_pool = create_pool("ptrcap",
6467 curproxy->nb_req_cap * sizeof(char *),
6468 MEM_F_SHARED);
6469 } else {
6470 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6471 proxy_type_str(curproxy), curproxy->id);
6472 err_code |= ERR_WARN;
6473 curproxy->to_log &= ~LW_REQHDR;
6474 curproxy->nb_req_cap = 0;
6475 }
6476 }
6477
6478 if (curproxy->nb_rsp_cap) {
6479 if (curproxy->mode == PR_MODE_HTTP) {
6480 curproxy->rsp_cap_pool = create_pool("ptrcap",
6481 curproxy->nb_rsp_cap * sizeof(char *),
6482 MEM_F_SHARED);
6483 } else {
6484 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6485 proxy_type_str(curproxy), curproxy->id);
6486 err_code |= ERR_WARN;
6487 curproxy->to_log &= ~LW_REQHDR;
6488 curproxy->nb_rsp_cap = 0;
6489 }
6490 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006491
Willy Tarreau196729e2012-05-31 19:30:26 +02006492 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006493 if (!(curproxy->cap & PR_CAP_FE)) {
6494 if (curproxy->logformat_string != default_http_log_format &&
6495 curproxy->logformat_string != default_tcp_log_format &&
6496 curproxy->logformat_string != clf_http_log_format)
6497 free(curproxy->logformat_string);
6498 curproxy->logformat_string = NULL;
6499 }
6500
Willy Tarreau196729e2012-05-31 19:30:26 +02006501 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006502 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006503
6504 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006505 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006506
Willy Tarreaubaaee002006-06-26 02:48:02 +02006507 /* first, we will invert the servers list order */
6508 newsrv = NULL;
6509 while (curproxy->srv) {
6510 struct server *next;
6511
6512 next = curproxy->srv->next;
6513 curproxy->srv->next = newsrv;
6514 newsrv = curproxy->srv;
6515 if (!next)
6516 break;
6517 curproxy->srv = next;
6518 }
6519
Willy Tarreaudd701652010-05-25 23:03:02 +02006520 /* assign automatic UIDs to servers which don't have one yet */
6521 next_id = 1;
6522 newsrv = curproxy->srv;
6523 while (newsrv != NULL) {
6524 if (!newsrv->puid) {
6525 /* server ID not set, use automatic numbering with first
6526 * spare entry starting with next_svid.
6527 */
6528 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6529 newsrv->conf.id.key = newsrv->puid = next_id;
6530 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6531 }
6532 next_id++;
6533 newsrv = newsrv->next;
6534 }
6535
Willy Tarreau20697042007-11-15 23:26:18 +01006536 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006537 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538
Willy Tarreau62c3be22012-01-20 13:12:32 +01006539 /*
6540 * If this server supports a maxconn parameter, it needs a dedicated
6541 * tasks to fill the emptied slots when a connection leaves.
6542 * Also, resolve deferred tracking dependency if needed.
6543 */
6544 newsrv = curproxy->srv;
6545 while (newsrv != NULL) {
6546 if (newsrv->minconn > newsrv->maxconn) {
6547 /* Only 'minconn' was specified, or it was higher than or equal
6548 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6549 * this will avoid further useless expensive computations.
6550 */
6551 newsrv->maxconn = newsrv->minconn;
6552 } else if (newsrv->maxconn && !newsrv->minconn) {
6553 /* minconn was not specified, so we set it to maxconn */
6554 newsrv->minconn = newsrv->maxconn;
6555 }
6556
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006557#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006558 if (newsrv->use_ssl || newsrv->check.use_ssl)
6559 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006560#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006561
Willy Tarreau62c3be22012-01-20 13:12:32 +01006562 if (newsrv->trackit) {
6563 struct proxy *px;
6564 struct server *srv;
6565 char *pname, *sname;
6566
6567 pname = newsrv->trackit;
6568 sname = strrchr(pname, '/');
6569
6570 if (sname)
6571 *sname++ = '\0';
6572 else {
6573 sname = pname;
6574 pname = NULL;
6575 }
6576
6577 if (pname) {
6578 px = findproxy(pname, PR_CAP_BE);
6579 if (!px) {
6580 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6581 proxy_type_str(curproxy), curproxy->id,
6582 newsrv->id, pname);
6583 cfgerr++;
6584 goto next_srv;
6585 }
6586 } else
6587 px = curproxy;
6588
6589 srv = findserver(px, sname);
6590 if (!srv) {
6591 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6592 proxy_type_str(curproxy), curproxy->id,
6593 newsrv->id, sname);
6594 cfgerr++;
6595 goto next_srv;
6596 }
6597
6598 if (!(srv->state & SRV_CHECKED)) {
6599 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6600 "tracking as it does not have checks enabled.\n",
6601 proxy_type_str(curproxy), curproxy->id,
6602 newsrv->id, px->id, srv->id);
6603 cfgerr++;
6604 goto next_srv;
6605 }
6606
6607 if (curproxy != px &&
6608 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6609 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6610 "tracking: disable-on-404 option inconsistency.\n",
6611 proxy_type_str(curproxy), curproxy->id,
6612 newsrv->id, px->id, srv->id);
6613 cfgerr++;
6614 goto next_srv;
6615 }
6616
6617 /* if the other server is forced disabled, we have to do the same here */
6618 if (srv->state & SRV_MAINTAIN) {
6619 newsrv->state |= SRV_MAINTAIN;
6620 newsrv->state &= ~SRV_RUNNING;
6621 newsrv->health = 0;
6622 }
6623
6624 newsrv->track = srv;
6625 newsrv->tracknext = srv->tracknext;
6626 srv->tracknext = newsrv;
6627
6628 free(newsrv->trackit);
6629 newsrv->trackit = NULL;
6630 }
6631 next_srv:
6632 newsrv = newsrv->next;
6633 }
6634
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006635 /* We have to initialize the server lookup mechanism depending
6636 * on what LB algorithm was choosen.
6637 */
6638
6639 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6640 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6641 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006642 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6643 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6644 init_server_map(curproxy);
6645 } else {
6646 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6647 fwrr_init_server_groups(curproxy);
6648 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006649 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006650
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006651 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006652 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6653 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6654 fwlc_init_server_tree(curproxy);
6655 } else {
6656 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6657 fas_init_server_tree(curproxy);
6658 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006659 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006660
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006661 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006662 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6663 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6664 chash_init_server_tree(curproxy);
6665 } else {
6666 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6667 init_server_map(curproxy);
6668 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006669 break;
6670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671
6672 if (curproxy->options & PR_O_LOGASAP)
6673 curproxy->to_log &= ~LW_BYTES;
6674
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006675 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006676 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006677 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6678 proxy_type_str(curproxy), curproxy->id);
6679 err_code |= ERR_WARN;
6680 }
6681
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006682 if (curproxy->mode != PR_MODE_HTTP) {
6683 int optnum;
6684
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006685 if (curproxy->uri_auth) {
6686 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6687 proxy_type_str(curproxy), curproxy->id);
6688 err_code |= ERR_WARN;
6689 curproxy->uri_auth = NULL;
6690 }
6691
Willy Tarreau87cf5142011-08-19 22:57:24 +02006692 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006693 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6694 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6695 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006696 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006697 }
6698
6699 if (curproxy->options & PR_O_ORGTO) {
6700 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6701 "originalto", proxy_type_str(curproxy), curproxy->id);
6702 err_code |= ERR_WARN;
6703 curproxy->options &= ~PR_O_ORGTO;
6704 }
6705
6706 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6707 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6708 (curproxy->cap & cfg_opts[optnum].cap) &&
6709 (curproxy->options & cfg_opts[optnum].val)) {
6710 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6711 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6712 err_code |= ERR_WARN;
6713 curproxy->options &= ~cfg_opts[optnum].val;
6714 }
6715 }
6716
6717 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6718 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6719 (curproxy->cap & cfg_opts2[optnum].cap) &&
6720 (curproxy->options2 & cfg_opts2[optnum].val)) {
6721 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6722 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6723 err_code |= ERR_WARN;
6724 curproxy->options2 &= ~cfg_opts2[optnum].val;
6725 }
6726 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006727
Willy Tarreauefa5f512010-03-30 20:13:29 +02006728#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006729 if (curproxy->conn_src.bind_hdr_occ) {
6730 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006731 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006732 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006733 err_code |= ERR_WARN;
6734 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006735#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006736 }
6737
Willy Tarreaubaaee002006-06-26 02:48:02 +02006738 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006739 * ensure that we're not cross-dressing a TCP server into HTTP.
6740 */
6741 newsrv = curproxy->srv;
6742 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006743 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006744 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6745 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006746 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006747 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006748
Willy Tarreau0cec3312011-10-31 13:49:26 +01006749 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6750 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6751 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6752 err_code |= ERR_WARN;
6753 }
6754
Willy Tarreauefa5f512010-03-30 20:13:29 +02006755#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006756 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6757 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006758 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 +01006759 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006760 err_code |= ERR_WARN;
6761 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006762#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006763 newsrv = newsrv->next;
6764 }
6765
Willy Tarreauc1a21672009-08-16 22:37:44 +02006766 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006767 if (!curproxy->accept)
6768 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006769
Willy Tarreauc1a21672009-08-16 22:37:44 +02006770 if (curproxy->tcp_req.inspect_delay ||
6771 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006772 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006773
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006774 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006775 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006776 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006777 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006778
6779 /* both TCP and HTTP must check switching rules */
6780 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6781 }
6782
6783 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006784 if (curproxy->tcp_req.inspect_delay ||
6785 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6786 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6787
Emeric Brun97679e72010-09-23 17:56:44 +02006788 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6789 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6790
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006791 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006792 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006793 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006794 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006795
6796 /* If the backend does requires RDP cookie persistence, we have to
6797 * enable the corresponding analyser.
6798 */
6799 if (curproxy->options2 & PR_O2_RDPC_PRST)
6800 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6801 }
6802
Emeric Brunc52962f2012-11-15 18:28:02 +01006803#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006804 /* Configure SSL for each bind line.
6805 * Note: if configuration fails at some point, the ->ctx member
6806 * remains NULL so that listeners can later detach.
6807 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006808 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006809 if (!bind_conf->is_ssl) {
6810 if (bind_conf->default_ctx) {
6811 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6812 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6813 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006814 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006815 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006816 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006817 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006818 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006819 cfgerr++;
6820 continue;
6821 }
6822
Emeric Brun4b3091e2012-09-24 15:48:52 +02006823 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006824 Alert("Unable to allocate SSL session cache.\n");
6825 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006826 continue;
6827 }
6828
Emeric Brunfc0421f2012-09-07 17:30:07 +02006829 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006830 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006831 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006832#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006833
Willy Tarreaue6b98942007-10-29 01:09:36 +01006834 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006835 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006836 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006837 if (!listener->luid) {
6838 /* listener ID not set, use automatic numbering with first
6839 * spare entry starting with next_luid.
6840 */
6841 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6842 listener->conf.id.key = listener->luid = next_id;
6843 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006844 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006845 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006846
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006847 /* enable separate counters */
6848 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6849 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006850 if (!listener->name)
6851 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006852 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006853
Willy Tarreaue6b98942007-10-29 01:09:36 +01006854 if (curproxy->options & PR_O_TCP_NOLING)
6855 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006856 if (!listener->maxconn)
6857 listener->maxconn = curproxy->maxconn;
6858 if (!listener->backlog)
6859 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006860 if (!listener->maxaccept)
6861 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6862
6863 /* we want to have an optimal behaviour on single process mode to
6864 * maximize the work at once, but in multi-process we want to keep
6865 * some fairness between processes, so we target half of the max
6866 * number of events to be balanced over all the processes the proxy
6867 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6868 * used to disable the limit.
6869 */
6870 if (listener->maxaccept > 0) {
6871 if (nbproc > 1)
6872 listener->maxaccept = (listener->maxaccept + 1) / 2;
6873 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6874 }
6875
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006876 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006877 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006878 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006879 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006880
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006881 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6882 listener->options |= LI_O_TCP_RULES;
6883
Willy Tarreaude3041d2010-05-31 10:56:17 +02006884 if (curproxy->mon_mask.s_addr)
6885 listener->options |= LI_O_CHK_MONNET;
6886
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006887 /* smart accept mode is automatic in HTTP mode */
6888 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006889 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006890 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6891 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006892 }
6893
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006894 /* Release unused SSL configs */
6895 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6896 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006897 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006898#ifdef USE_OPENSSL
6899 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006900 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006901 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006902 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006903 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006904#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006905 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006906
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006907 /* Check multi-process mode compatibility for the current proxy */
6908 if (global.nbproc > 1) {
6909 int nbproc = 0;
6910 if (curproxy->bind_proc) {
6911 int proc;
6912 for (proc = 0; proc < global.nbproc; proc++) {
6913 if (curproxy->bind_proc & (1 << proc)) {
6914 nbproc++;
6915 }
6916 }
6917 } else {
6918 nbproc = global.nbproc;
6919 }
6920 if (curproxy->table.peers.name) {
6921 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6922 curproxy->id);
6923 cfgerr++;
6924 }
6925 if (nbproc > 1) {
6926 if (curproxy->uri_auth) {
6927 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6928 curproxy->id);
6929 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6930 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6931 curproxy->id);
6932 }
6933 }
6934 if (curproxy->appsession_name) {
6935 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6936 curproxy->id);
6937 }
6938 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6939 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6940 curproxy->id);
6941 }
6942 }
6943 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006944
6945 /* create the task associated with the proxy */
6946 curproxy->task = task_new();
6947 if (curproxy->task) {
6948 curproxy->task->context = curproxy;
6949 curproxy->task->process = manage_proxy;
6950 /* no need to queue, it will be done automatically if some
6951 * listener gets limited.
6952 */
6953 curproxy->task->expire = TICK_ETERNITY;
6954 } else {
6955 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6956 curproxy->id);
6957 cfgerr++;
6958 }
6959
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960 curproxy = curproxy->next;
6961 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006962
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006963 /* Check multi-process mode compatibility */
6964 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006965 if (global.stats_fe && !global.stats_fe->bind_proc) {
6966 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 +01006967 }
6968 }
6969
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006970 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6971 struct auth_users *curuser;
6972 int g;
6973
6974 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6975 unsigned int group_mask = 0;
6976 char *group = NULL;
6977
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006978 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006979 continue;
6980
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006981 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006982
6983 for (g = 0; g < curuserlist->grpcnt; g++)
6984 if (!strcmp(curuserlist->groups[g], group))
6985 break;
6986
6987 if (g == curuserlist->grpcnt) {
6988 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6989 curuserlist->name, group, curuser->user);
6990 err_code |= ERR_ALERT | ERR_FATAL;
6991 goto out;
6992 }
6993
6994 group_mask |= (1 << g);
6995 }
6996
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006997 free(curuser->u.groups);
6998 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006999 }
7000
7001 for (g = 0; g < curuserlist->grpcnt; g++) {
7002 char *user = NULL;
7003
7004 if (!curuserlist->groupusers[g])
7005 continue;
7006
7007 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7008 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7009 if (!strcmp(curuser->user, user))
7010 break;
7011
7012 if (!curuser) {
7013 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7014 curuserlist->name, user, curuserlist->groups[g]);
7015 err_code |= ERR_ALERT | ERR_FATAL;
7016 goto out;
7017 }
7018
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007019 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007020 }
7021
7022 free(curuserlist->groupusers[g]);
7023 }
7024
7025 free(curuserlist->groupusers);
7026
7027#ifdef DEBUG_AUTH
7028 for (g = 0; g < curuserlist->grpcnt; g++) {
7029 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7030
7031 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007032 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007033 fprintf(stderr, " %s", curuser->user);
7034 }
7035
7036 fprintf(stderr, "\n");
7037 }
7038#endif
7039
Willy Tarreaufbb78422011-06-05 15:38:35 +02007040 }
7041
7042 /* automatically compute fullconn if not set. We must not do it in the
7043 * loop above because cross-references are not yet fully resolved.
7044 */
7045 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7046 /* If <fullconn> is not set, let's set it to 10% of the sum of
7047 * the possible incoming frontend's maxconns.
7048 */
7049 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7050 struct proxy *fe;
7051 int total = 0;
7052
7053 /* sum up the number of maxconns of frontends which
7054 * reference this backend at least once or which are
7055 * the same one ('listen').
7056 */
7057 for (fe = proxy; fe; fe = fe->next) {
7058 struct switching_rule *rule;
7059 struct hdr_exp *exp;
7060 int found = 0;
7061
7062 if (!(fe->cap & PR_CAP_FE))
7063 continue;
7064
7065 if (fe == curproxy) /* we're on a "listen" instance */
7066 found = 1;
7067
7068 if (fe->defbe.be == curproxy) /* "default_backend" */
7069 found = 1;
7070
7071 /* check if a "use_backend" rule matches */
7072 if (!found) {
7073 list_for_each_entry(rule, &fe->switching_rules, list) {
7074 if (rule->be.backend == curproxy) {
7075 found = 1;
7076 break;
7077 }
7078 }
7079 }
7080
7081 /* check if a "reqsetbe" rule matches */
7082 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7083 if (exp->action == ACT_SETBE &&
7084 (struct proxy *)exp->replace == curproxy) {
7085 found = 1;
7086 break;
7087 }
7088 }
7089
7090 /* now we've checked all possible ways to reference a backend
7091 * from a frontend.
7092 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007093 if (!found)
7094 continue;
7095 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007096 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007097 /* we have the sum of the maxconns in <total>. We only
7098 * keep 10% of that sum to set the default fullconn, with
7099 * a hard minimum of 1 (to avoid a divide by zero).
7100 */
7101 curproxy->fullconn = (total + 9) / 10;
7102 if (!curproxy->fullconn)
7103 curproxy->fullconn = 1;
7104 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007105 }
7106
Willy Tarreau056f5682010-06-06 15:51:11 +02007107 /* initialize stick-tables on backend capable proxies. This must not
7108 * be done earlier because the data size may be discovered while parsing
7109 * other proxies.
7110 */
7111 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007112 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007113
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007114 /*
7115 * Recount currently required checks.
7116 */
7117
7118 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7119 int optnum;
7120
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007121 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7122 if (curproxy->options & cfg_opts[optnum].val)
7123 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007124
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007125 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7126 if (curproxy->options2 & cfg_opts2[optnum].val)
7127 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007128 }
7129
Willy Tarreau122541c2011-09-07 21:24:49 +02007130 if (peers) {
7131 struct peers *curpeers = peers, **last;
7132 struct peer *p, *pb;
7133
7134 /* Remove all peers sections which don't have a valid listener.
7135 * This can happen when a peers section is never referenced and
7136 * does not contain a local peer.
7137 */
7138 last = &peers;
7139 while (*last) {
7140 curpeers = *last;
7141 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007142 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007143 last = &curpeers->next;
7144 continue;
7145 }
7146
7147 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7148 curpeers->id, localpeer);
7149
7150 p = curpeers->remote;
7151 while (p) {
7152 pb = p->next;
7153 free(p->id);
7154 free(p);
7155 p = pb;
7156 }
7157
7158 /* Destroy and unlink this curpeers section.
7159 * Note: curpeers is backed up into *last.
7160 */
7161 free(curpeers->id);
7162 curpeers = curpeers->next;
7163 free(*last);
7164 *last = curpeers;
7165 }
7166 }
7167
Willy Tarreau34eb6712011-10-24 18:15:04 +02007168 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007169 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007170 MEM_F_SHARED);
7171
Willy Tarreaubb925012009-07-23 13:36:36 +02007172 if (cfgerr > 0)
7173 err_code |= ERR_ALERT | ERR_FATAL;
7174 out:
7175 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007176}
7177
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007178/*
7179 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7180 * parsing sessions.
7181 */
7182void cfg_register_keywords(struct cfg_kw_list *kwl)
7183{
7184 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7185}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007186
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007187/*
7188 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7189 */
7190void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7191{
7192 LIST_DEL(&kwl->list);
7193 LIST_INIT(&kwl->list);
7194}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007195
7196/*
7197 * Local variables:
7198 * c-indent-level: 8
7199 * c-basic-offset: 8
7200 * End:
7201 */