blob: b42b4634fbcc9fa3a8a238b2c2a4c760df60ecd0 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100209 struct sockaddr_storage ss, *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100217 ss2 = str2sa_range(str, &port, &end, err,
218 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
219 if (!ss2)
220 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100222 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100223 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100228 if (!port || !end) {
229 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
230 goto fail;
231 }
232
Emeric Bruned760922010-10-22 17:59:25 +0200233 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200234 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200235 goto fail;
236 }
237
238 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200239 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200240 goto fail;
241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242 }
243
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100244 /* OK the address looks correct */
245 ss = *ss2;
246
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247 for (; port <= end; port++) {
248 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100249 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200250 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
251 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
252 l->frontend = curproxy;
253 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
255 l->fd = -1;
256 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200257 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100258 l->state = LI_INIT;
259
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 tcpv4_add_listener(l);
263 }
Emeric Bruned760922010-10-22 17:59:25 +0200264 else if (ss.ss_family == AF_INET6) {
265 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
266 tcpv6_add_listener(l);
267 }
268 else {
Emeric Bruned760922010-10-22 17:59:25 +0200269 uxst_add_listener(l);
270 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200271
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200272 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100273 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 } /* end for(port) */
275 } /* end while(next) */
276 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200277 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 fail:
279 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281}
282
Willy Tarreau977b8e42006-12-29 14:19:17 +0100283/*
284 * Sends a warning if proxy <proxy> does not have at least one of the
285 * capabilities in <cap>. An optionnal <hint> may be added at the end
286 * of the warning to help the user. Returns 1 if a warning was emitted
287 * or 0 if the condition is valid.
288 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100289int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100290{
291 char *msg;
292
293 switch (cap) {
294 case PR_CAP_BE: msg = "no backend"; break;
295 case PR_CAP_FE: msg = "no frontend"; break;
296 case PR_CAP_RS: msg = "no ruleset"; break;
297 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
298 default: msg = "not enough"; break;
299 }
300
301 if (!(proxy->cap & cap)) {
302 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100303 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100304 return 1;
305 }
306 return 0;
307}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200308
Willy Tarreau61d18892009-03-31 10:49:21 +0200309/* Report a warning if a rule is placed after a 'block' rule.
310 * Return 1 if the warning has been emitted, otherwise 0.
311 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100312int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200313{
314 if (!LIST_ISEMPTY(&proxy->block_cond)) {
315 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
316 file, line, arg);
317 return 1;
318 }
319 return 0;
320}
321
322/* Report a warning if a rule is placed after a reqrewrite rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100325int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200326{
327 if (proxy->req_exp) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
335/* Report a warning if a rule is placed after a reqadd rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100340 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
348/* Report a warning if a rule is placed after a redirect rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100351int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200352{
353 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
354 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
361/* Report a warning if a rule is placed after a 'use_backend' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
378 warnif_rule_after_reqadd(proxy, file, line, arg) ||
379 warnif_rule_after_redirect(proxy, file, line, arg) ||
380 warnif_rule_after_use_backend(proxy, file, line, arg);
381}
382
383/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
387 warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
391/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 return warnif_rule_after_redirect(proxy, file, line, arg) ||
395 warnif_rule_after_use_backend(proxy, file, line, arg);
396}
397
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100398/* Report it if a request ACL condition uses some response-only parameters. It
399 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
400 * Note that <cond> may be NULL and then will be ignored.
401 */
402static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
403{
404 struct acl *acl;
405
406 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
407 return 0;
408
409 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
410 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
411 file, line, acl ? acl->name : "(unknown)");
412 return ERR_WARN;
413}
414
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100415/* Report it if a request ACL condition uses some request-only volatile parameters.
416 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
417 * Note that <cond> may be NULL and then will be ignored.
418 */
419static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
420{
421 struct acl *acl;
422
423 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
424 return 0;
425
426 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
427 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
428 file, line, acl ? acl->name : "(unknown)");
429 return ERR_WARN;
430}
431
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100432
Willy Tarreaubaaee002006-06-26 02:48:02 +0200433/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200434 * parse a line in a <global> section. Returns the error code, 0 if OK, or
435 * any combination of :
436 * - ERR_ABORT: must abort ASAP
437 * - ERR_FATAL: we can continue parsing but not start the service
438 * - ERR_WARN: a warning has been emitted
439 * - ERR_ALERT: an alert has been emitted
440 * Only the two first ones can stop processing, the two others are just
441 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200443int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444{
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200446 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200447
448 if (!strcmp(args[0], "global")) { /* new section */
449 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200452 else if (!strcmp(args[0], "ca-base")) {
453#ifdef USE_OPENSSL
454 if (global.ca_base != NULL) {
455 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
456 err_code |= ERR_ALERT;
457 goto out;
458 }
459 if (*(args[1]) == 0) {
460 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
461 err_code |= ERR_ALERT | ERR_FATAL;
462 goto out;
463 }
464 global.ca_base = strdup(args[1]);
465#else
466 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
467 err_code |= ERR_ALERT | ERR_FATAL;
468 goto out;
469#endif
470 }
471 else if (!strcmp(args[0], "crt-base")) {
472#ifdef USE_OPENSSL
473 if (global.crt_base != NULL) {
474 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
475 err_code |= ERR_ALERT;
476 goto out;
477 }
478 if (*(args[1]) == 0) {
479 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
480 err_code |= ERR_ALERT | ERR_FATAL;
481 goto out;
482 }
483 global.crt_base = strdup(args[1]);
484#else
485 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488#endif
489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490 else if (!strcmp(args[0], "daemon")) {
491 global.mode |= MODE_DAEMON;
492 }
493 else if (!strcmp(args[0], "debug")) {
494 global.mode |= MODE_DEBUG;
495 }
496 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100497 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200498 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200499 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100500 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200502 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100503 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100505 else if (!strcmp(args[0], "nosplice")) {
506 global.tune.options &= ~GTUNE_USE_SPLICE;
507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 else if (!strcmp(args[0], "quiet")) {
509 global.mode |= MODE_QUIET;
510 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200511 else if (!strcmp(args[0], "tune.maxpollevents")) {
512 if (global.tune.maxpollevents != 0) {
513 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200514 err_code |= ERR_ALERT;
515 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200516 }
517 if (*(args[1]) == 0) {
518 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200519 err_code |= ERR_ALERT | ERR_FATAL;
520 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200521 }
522 global.tune.maxpollevents = atol(args[1]);
523 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100524 else if (!strcmp(args[0], "tune.maxaccept")) {
525 if (global.tune.maxaccept != 0) {
526 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200527 err_code |= ERR_ALERT;
528 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100529 }
530 if (*(args[1]) == 0) {
531 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200532 err_code |= ERR_ALERT | ERR_FATAL;
533 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100534 }
535 global.tune.maxaccept = atol(args[1]);
536 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200537 else if (!strcmp(args[0], "tune.chksize")) {
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
542 }
543 global.tune.chksize = atol(args[1]);
544 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200545#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100546 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200547 if (*(args[1]) == 0) {
548 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT | ERR_FATAL;
550 goto out;
551 }
552 global.tune.sslcachesize = atol(args[1]);
553 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100554 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
555 unsigned int ssllifetime;
556 const char *res;
557
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563
564 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
565 if (res) {
566 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
567 file, linenum, *res, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571
572 global.tune.ssllifetime = ssllifetime;
573 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100574 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.tune.ssl_max_record = atol(args[1]);
581 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200582#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200583 else if (!strcmp(args[0], "tune.bufsize")) {
584 if (*(args[1]) == 0) {
585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589 global.tune.bufsize = atol(args[1]);
590 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
591 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100592 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200593 }
594 else if (!strcmp(args[0], "tune.maxrewrite")) {
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.maxrewrite = atol(args[1]);
601 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
602 global.tune.maxrewrite = global.tune.bufsize / 2;
603 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100604 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
605 if (global.tune.client_rcvbuf != 0) {
606 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT;
608 goto out;
609 }
610 if (*(args[1]) == 0) {
611 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
612 err_code |= ERR_ALERT | ERR_FATAL;
613 goto out;
614 }
615 global.tune.client_rcvbuf = atol(args[1]);
616 }
617 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
618 if (global.tune.server_rcvbuf != 0) {
619 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
620 err_code |= ERR_ALERT;
621 goto out;
622 }
623 if (*(args[1]) == 0) {
624 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT | ERR_FATAL;
626 goto out;
627 }
628 global.tune.server_rcvbuf = atol(args[1]);
629 }
630 else if (!strcmp(args[0], "tune.sndbuf.client")) {
631 if (global.tune.client_sndbuf != 0) {
632 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT;
634 goto out;
635 }
636 if (*(args[1]) == 0) {
637 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
640 }
641 global.tune.client_sndbuf = atol(args[1]);
642 }
643 else if (!strcmp(args[0], "tune.sndbuf.server")) {
644 if (global.tune.server_sndbuf != 0) {
645 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
646 err_code |= ERR_ALERT;
647 goto out;
648 }
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
653 }
654 global.tune.server_sndbuf = atol(args[1]);
655 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200656 else if (!strcmp(args[0], "tune.pipesize")) {
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.pipesize = atol(args[1]);
663 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100664 else if (!strcmp(args[0], "tune.http.cookielen")) {
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.cookie_len = atol(args[1]) + 1;
671 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200672 else if (!strcmp(args[0], "tune.http.maxhdr")) {
673 if (*(args[1]) == 0) {
674 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678 global.tune.max_http_hdr = atol(args[1]);
679 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100680 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
681#ifdef USE_ZLIB
682 if (*args[1]) {
683 global.tune.zlibmemlevel = atoi(args[1]);
684 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
685 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
686 file, linenum, args[0]);
687 err_code |= ERR_ALERT | ERR_FATAL;
688 goto out;
689 }
690 } else {
691 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
692 file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696#else
697 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
700#endif
701 }
702 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
703#ifdef USE_ZLIB
704 if (*args[1]) {
705 global.tune.zlibwindowsize = atoi(args[1]);
706 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
707 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
708 file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 } else {
713 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
714 file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717 }
718#else
719 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722#endif
723 }
William Lallemandf3747832012-11-09 12:33:10 +0100724 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
725 if (*args[1]) {
726 global.tune.comp_maxlevel = atoi(args[1]);
727 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
728 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
729 file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 } else {
734 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
735 file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 else if (!strcmp(args[0], "uid")) {
741 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200742 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT;
744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 }
751 global.uid = atol(args[1]);
752 }
753 else if (!strcmp(args[0], "gid")) {
754 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200755 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 if (*(args[1]) == 0) {
760 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200763 }
764 global.gid = atol(args[1]);
765 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200766 /* user/group name handling */
767 else if (!strcmp(args[0], "user")) {
768 struct passwd *ha_user;
769 if (global.uid != 0) {
770 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT;
772 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200773 }
774 errno = 0;
775 ha_user = getpwnam(args[1]);
776 if (ha_user != NULL) {
777 global.uid = (int)ha_user->pw_uid;
778 }
779 else {
780 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200781 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200782 }
783 }
784 else if (!strcmp(args[0], "group")) {
785 struct group *ha_group;
786 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200787 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT;
789 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200790 }
791 errno = 0;
792 ha_group = getgrnam(args[1]);
793 if (ha_group != NULL) {
794 global.gid = (int)ha_group->gr_gid;
795 }
796 else {
797 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200799 }
800 }
801 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 global.nbproc = atol(args[1]);
809 }
810 else if (!strcmp(args[0], "maxconn")) {
811 if (global.maxconn != 0) {
812 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200815 }
816 if (*(args[1]) == 0) {
817 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200818 err_code |= ERR_ALERT | ERR_FATAL;
819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 }
821 global.maxconn = atol(args[1]);
822#ifdef SYSTEM_MAXCONN
823 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
824 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
825 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200827 }
828#endif /* SYSTEM_MAXCONN */
829 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200830 else if (!strcmp(args[0], "maxsslconn")) {
831#ifdef USE_OPENSSL
832 if (*(args[1]) == 0) {
833 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 global.maxsslconn = atol(args[1]);
838#else
Emeric Brun0914df82012-10-02 18:45:42 +0200839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200842#endif
843 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200844 else if (!strcmp(args[0], "maxconnrate")) {
845 if (global.cps_lim != 0) {
846 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT;
848 goto out;
849 }
850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
854 }
855 global.cps_lim = atol(args[1]);
856 }
William Lallemandd85f9172012-11-09 17:05:39 +0100857 else if (!strcmp(args[0], "maxcomprate")) {
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 global.comp_rate_lim = atoi(args[1]) * 1024;
864 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100865 else if (!strcmp(args[0], "maxpipes")) {
866 if (global.maxpipes != 0) {
867 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
869 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100870 }
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100875 }
876 global.maxpipes = atol(args[1]);
877 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100878 else if (!strcmp(args[0], "maxzlibmem")) {
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
William Lallemande3a7d992012-11-20 11:25:20 +0100884 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100885 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100886 else if (!strcmp(args[0], "maxcompcpuusage")) {
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100893 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100894 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
897 }
898}
899
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 else if (!strcmp(args[0], "ulimit-n")) {
901 if (global.rlimit_nofile != 0) {
902 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 if (*(args[1]) == 0) {
907 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 global.rlimit_nofile = atol(args[1]);
912 }
913 else if (!strcmp(args[0], "chroot")) {
914 if (global.chroot != NULL) {
915 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 if (*(args[1]) == 0) {
920 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200921 err_code |= ERR_ALERT | ERR_FATAL;
922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 }
924 global.chroot = strdup(args[1]);
925 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200926 else if (!strcmp(args[0], "description")) {
927 int i, len=0;
928 char *d;
929
930 if (!*args[1]) {
931 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
932 file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936
937 for(i=1; *args[i]; i++)
938 len += strlen(args[i])+1;
939
940 if (global.desc)
941 free(global.desc);
942
943 global.desc = d = (char *)calloc(1, len);
944
945 d += sprintf(d, "%s", args[1]);
946 for(i=2; *args[i]; i++)
947 d += sprintf(d, " %s", args[i]);
948 }
949 else if (!strcmp(args[0], "node")) {
950 int i;
951 char c;
952
953 for (i=0; args[1][i]; i++) {
954 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100955 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
956 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200957 break;
958 }
959
960 if (!i || args[1][i]) {
961 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
962 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
963 file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967
968 if (global.node)
969 free(global.node);
970
971 global.node = strdup(args[1]);
972 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 else if (!strcmp(args[0], "pidfile")) {
974 if (global.pidfile != NULL) {
975 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT;
977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 if (*(args[1]) == 0) {
980 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200981 err_code |= ERR_ALERT | ERR_FATAL;
982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 }
984 global.pidfile = strdup(args[1]);
985 }
Emeric Bruned760922010-10-22 17:59:25 +0200986 else if (!strcmp(args[0], "unix-bind")) {
987 int cur_arg = 1;
988 while (*(args[cur_arg])) {
989 if (!strcmp(args[cur_arg], "prefix")) {
990 if (global.unix_bind.prefix != NULL) {
991 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
992 err_code |= ERR_ALERT;
993 cur_arg += 2;
994 continue;
995 }
996
997 if (*(args[cur_arg+1]) == 0) {
998 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1003 cur_arg += 2;
1004 continue;
1005 }
1006
1007 if (!strcmp(args[cur_arg], "mode")) {
1008
1009 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1010 cur_arg += 2;
1011 continue;
1012 }
1013
1014 if (!strcmp(args[cur_arg], "uid")) {
1015
1016 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1017 cur_arg += 2;
1018 continue;
1019 }
1020
1021 if (!strcmp(args[cur_arg], "gid")) {
1022
1023 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1024 cur_arg += 2;
1025 continue;
1026 }
1027
1028 if (!strcmp(args[cur_arg], "user")) {
1029 struct passwd *user;
1030
1031 user = getpwnam(args[cur_arg + 1]);
1032 if (!user) {
1033 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1034 file, linenum, args[0], args[cur_arg + 1 ]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038
1039 global.unix_bind.ux.uid = user->pw_uid;
1040 cur_arg += 2;
1041 continue;
1042 }
1043
1044 if (!strcmp(args[cur_arg], "group")) {
1045 struct group *group;
1046
1047 group = getgrnam(args[cur_arg + 1]);
1048 if (!group) {
1049 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1050 file, linenum, args[0], args[cur_arg + 1 ]);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
1053 }
1054
1055 global.unix_bind.ux.gid = group->gr_gid;
1056 cur_arg += 2;
1057 continue;
1058 }
1059
Willy Tarreaub48f9582011-09-05 01:17:06 +02001060 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001061 file, linenum, args[0]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 }
William Lallemand0f99e342011-10-12 17:50:54 +02001066 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1067 /* delete previous herited or defined syslog servers */
1068 struct logsrv *back;
1069 struct logsrv *tmp;
1070
1071 if (*(args[1]) != 0) {
1072 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076
1077 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1078 LIST_DEL(&tmp->list);
1079 free(tmp);
1080 }
1081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001083 struct sockaddr_storage *sk;
1084 int port1, port2;
1085 char *err_msg = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02001086 struct logsrv *logsrv;
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (*(args[1]) == 0 || *(args[2]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
William Lallemand0f99e342011-10-12 17:50:54 +02001093
1094 logsrv = calloc(1, sizeof(struct logsrv));
1095
1096 logsrv->facility = get_log_facility(args[2]);
1097 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001099 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001100 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101 }
1102
William Lallemand0f99e342011-10-12 17:50:54 +02001103 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001104 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001105 logsrv->level = get_log_level(args[3]);
1106 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001108 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001109 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001110 }
1111 }
1112
William Lallemand0f99e342011-10-12 17:50:54 +02001113 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001114 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001115 logsrv->minlvl = get_log_level(args[4]);
1116 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001117 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001120 }
1121 }
1122
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001123 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
1124 if (!sk) {
1125 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], err_msg);
1126 err_code |= ERR_ALERT | ERR_FATAL;
1127 free(err_msg);
1128 free(logsrv);
1129 goto out;
1130 }
1131 logsrv->addr = *sk;
1132 free(err_msg);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001133
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001134 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001135 if (port1 != port2) {
1136 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1137 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001138 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001139 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001140 goto out;
1141 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001142
William Lallemand0f99e342011-10-12 17:50:54 +02001143 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001144 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001145 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147
William Lallemand0f99e342011-10-12 17:50:54 +02001148 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001149 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001150 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1151 char *name;
1152 int len;
1153
1154 if (global.log_send_hostname != NULL) {
1155 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1156 err_code |= ERR_ALERT;
1157 goto out;
1158 }
1159
1160 if (*(args[1]))
1161 name = args[1];
1162 else
1163 name = hostname;
1164
1165 len = strlen(name);
1166
1167 /* We'll add a space after the name to respect the log format */
1168 free(global.log_send_hostname);
1169 global.log_send_hostname = malloc(len + 2);
1170 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1171 }
Kevinm48936af2010-12-22 16:08:21 +00001172 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
1177 }
1178 free(global.log_tag);
1179 global.log_tag = strdup(args[1]);
1180 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001181 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1182 if (global.spread_checks != 0) {
1183 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001184 err_code |= ERR_ALERT;
1185 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001186 }
1187 if (*(args[1]) == 0) {
1188 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001191 }
1192 global.spread_checks = atol(args[1]);
1193 if (global.spread_checks < 0 || global.spread_checks > 50) {
1194 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001197 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001198 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1199#ifdef USE_CPU_AFFINITY
1200 int cur_arg, i;
1201 unsigned int proc = 0;
1202 unsigned long cpus = 0;
1203
1204 if (strcmp(args[1], "all") == 0)
1205 proc = 0xFFFFFFFF;
1206 else if (strcmp(args[1], "odd") == 0)
1207 proc = 0x55555555;
1208 else if (strcmp(args[1], "even") == 0)
1209 proc = 0xAAAAAAAA;
1210 else {
1211 proc = atoi(args[1]);
1212 if (proc >= 1 && proc <= 32)
1213 proc = 1 << (proc - 1);
1214 }
1215
1216 if (!proc || !*args[2]) {
1217 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1218 file, linenum, args[0]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 cur_arg = 2;
1224 while (*args[cur_arg]) {
1225 unsigned int low, high;
1226
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001227 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001228 char *dash = strchr(args[cur_arg], '-');
1229
1230 low = high = str2uic(args[cur_arg]);
1231 if (dash)
1232 high = str2uic(dash + 1);
1233
1234 if (high < low) {
1235 unsigned int swap = low;
1236 low = high;
1237 high = swap;
1238 }
1239
1240 if (low < 0 || high >= sizeof(long) * 8) {
1241 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1242 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 while (low <= high)
1248 cpus |= 1UL << low++;
1249 }
1250 else {
1251 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1252 file, linenum, args[0], args[cur_arg]);
1253 err_code |= ERR_ALERT | ERR_FATAL;
1254 goto out;
1255 }
1256 cur_arg++;
1257 }
1258 for (i = 0; i < 32; i++)
1259 if (proc & (1 << i))
1260 global.cpu_map[i] = cpus;
1261#else
1262 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265#endif
1266 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001267 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001268 struct cfg_kw_list *kwl;
1269 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001270 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001271
1272 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1273 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1274 if (kwl->kw[index].section != CFG_GLOBAL)
1275 continue;
1276 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001277 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001278 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001279 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001280 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001281 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001282 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001283 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001284 err_code |= ERR_WARN;
1285 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001286 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001287 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001288 }
1289 }
1290 }
1291
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001293 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001294 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001295
Willy Tarreau058e9072009-07-20 09:30:05 +02001296 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001297 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001298 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299}
1300
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001301void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001303 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 defproxy.mode = PR_MODE_TCP;
1305 defproxy.state = PR_STNEW;
1306 defproxy.maxconn = cfg_maxpconn;
1307 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001308
1309 defproxy.defsrv.inter = DEF_CHKINTR;
1310 defproxy.defsrv.fastinter = 0;
1311 defproxy.defsrv.downinter = 0;
1312 defproxy.defsrv.rise = DEF_RISETIME;
1313 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001314 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001315 defproxy.defsrv.maxqueue = 0;
1316 defproxy.defsrv.minconn = 0;
1317 defproxy.defsrv.maxconn = 0;
1318 defproxy.defsrv.slowstart = 0;
1319 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1320 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1321 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322}
1323
Willy Tarreauade5ec42010-01-28 19:33:49 +01001324
1325static int create_cond_regex_rule(const char *file, int line,
1326 struct proxy *px, int dir, int action, int flags,
1327 const char *cmd, const char *reg, const char *repl,
1328 const char **cond_start)
1329{
1330 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001331 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001332 const char *err;
1333 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001334 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001335
1336 if (px == &defproxy) {
1337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto err;
1340 }
1341
1342 if (*reg == 0) {
1343 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1344 err_code |= ERR_ALERT | ERR_FATAL;
1345 goto err;
1346 }
1347
1348 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1349 err_code |= ERR_WARN;
1350
Willy Tarreau5321c422010-01-28 20:35:13 +01001351 if (cond_start &&
1352 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001353 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1354 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1355 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto err;
1358 }
1359 }
1360 else if (cond_start && **cond_start) {
1361 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1362 file, line, cmd, *cond_start);
1363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto err;
1365 }
1366
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001367 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001368 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001369 else
1370 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001371
Willy Tarreauade5ec42010-01-28 19:33:49 +01001372 preg = calloc(1, sizeof(regex_t));
1373 if (!preg) {
1374 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1375 err_code = ERR_ALERT | ERR_FATAL;
1376 goto err;
1377 }
1378
1379 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1380 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1381 err_code = ERR_ALERT | ERR_FATAL;
1382 goto err;
1383 }
1384
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001385 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001386 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001387 if (repl && err) {
1388 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1389 file, line, cmd, *err);
1390 err_code |= ERR_ALERT | ERR_FATAL;
1391 goto err;
1392 }
1393
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001394 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001395 err_code |= ERR_WARN;
1396
Willy Tarreauf4068b62012-05-08 17:37:49 +02001397 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001398 return err_code;
1399 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001400 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001401 free(preg);
1402 return err_code;
1403}
1404
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001407 * Returns the error code, 0 if OK, or any combination of :
1408 * - ERR_ABORT: must abort ASAP
1409 * - ERR_FATAL: we can continue parsing but not start the service
1410 * - ERR_WARN: a warning has been emitted
1411 * - ERR_ALERT: an alert has been emitted
1412 * Only the two first ones can stop processing, the two others are just
1413 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001415int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1416{
1417 static struct peers *curpeers = NULL;
1418 struct peer *newpeer = NULL;
1419 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001420 struct bind_conf *bind_conf;
1421 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001422 int err_code = 0;
1423
1424 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001425 if (!*args[1]) {
1426 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1427 err_code |= ERR_ALERT | ERR_FATAL;
1428 goto out;
1429 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001430
1431 err = invalid_char(args[1]);
1432 if (err) {
1433 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1434 file, linenum, *err, args[0], args[1]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001436 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001437 }
1438
1439 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1440 /*
1441 * If there are two proxies with the same name only following
1442 * combinations are allowed:
1443 */
1444 if (strcmp(curpeers->id, args[1]) == 0) {
1445 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1446 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1447 err_code |= ERR_WARN;
1448 }
1449 }
1450
1451 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1453 err_code |= ERR_ALERT | ERR_ABORT;
1454 goto out;
1455 }
1456
1457 curpeers->next = peers;
1458 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001459 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001460 curpeers->conf.line = linenum;
1461 curpeers->last_change = now.tv_sec;
1462 curpeers->id = strdup(args[1]);
1463 }
1464 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001465 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001466 int port1, port2;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001467 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001468
1469 if (!*args[2]) {
1470 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1471 file, linenum, args[0]);
1472 err_code |= ERR_ALERT | ERR_FATAL;
1473 goto out;
1474 }
1475
1476 err = invalid_char(args[1]);
1477 if (err) {
1478 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1479 file, linenum, *err, args[1]);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto out;
1482 }
1483
1484 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1485 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1486 err_code |= ERR_ALERT | ERR_ABORT;
1487 goto out;
1488 }
1489
1490 /* the peers are linked backwards first */
1491 curpeers->count++;
1492 newpeer->next = curpeers->remote;
1493 curpeers->remote = newpeer;
1494 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001495 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001496 newpeer->conf.line = linenum;
1497
1498 newpeer->last_change = now.tv_sec;
1499 newpeer->id = strdup(args[1]);
1500
Willy Tarreaud393a622013-03-04 18:22:00 +01001501 sk = str2sa_range(args[2], &port1, &port2, NULL, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001502 if (!sk) {
1503 Alert("parsing [%s:%d] : '%s %s' : unknown host in '%s'\n", file, linenum, args[0], args[1], args[2]);
1504 err_code |= ERR_ALERT | ERR_FATAL;
1505 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001506 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001507
1508 if (port1 != port2) {
1509 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1510 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
Willy Tarreau2aa38802013-02-20 19:20:59 +01001515 if (!port1) {
1516 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1517 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001521
Emeric Brun32da3c42010-09-23 18:39:19 +02001522 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001523 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001524 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001525 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001526
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001527 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001528 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1529 file, linenum, newpeer->addr.ss_family, args[2]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533
Emeric Brun32da3c42010-09-23 18:39:19 +02001534 if (strcmp(newpeer->id, localpeer) == 0) {
1535 /* Current is local peer, it define a frontend */
1536 newpeer->local = 1;
1537
1538 if (!curpeers->peers_fe) {
1539 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1540 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1541 err_code |= ERR_ALERT | ERR_ABORT;
1542 goto out;
1543 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001544
Willy Tarreau237250c2011-07-29 01:49:03 +02001545 init_new_proxy(curpeers->peers_fe);
1546 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001547
1548 curpeers->peers_fe->last_change = now.tv_sec;
1549 curpeers->peers_fe->id = strdup(args[1]);
1550 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001551 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001552 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1553 curpeers->peers_fe->timeout.connect = 5000;
1554 curpeers->peers_fe->accept = peer_accept;
1555 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001556 curpeers->peers_fe->conf.file = strdup(file);
1557 curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558
1559 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1560
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001561 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1562 if (err_msg && *err_msg) {
1563 indent_msg(&err_msg, 2);
1564 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1565 }
1566 else
1567 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1568 file, linenum, args[0], args[1], args[2]);
1569 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 err_code |= ERR_FATAL;
1571 goto out;
1572 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001573
1574 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1575 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1576 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1577 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1578 l->accept = session_accept;
1579 l->handler = process_session;
1580 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1581 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1582 global.maxsock += l->maxconn;
1583 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001584 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001585 else {
1586 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1587 file, linenum, args[0], args[1],
1588 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1589 err_code |= ERR_FATAL;
1590 goto out;
1591 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001592 }
1593 } /* neither "peer" nor "peers" */
1594 else if (*args[0] != 0) {
1595 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
1598 }
1599
1600out:
1601 return err_code;
1602}
1603
1604
Willy Tarreau3842f002009-06-14 11:39:52 +02001605int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606{
1607 static struct proxy *curproxy = NULL;
1608 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001609 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001610 int rc;
1611 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001612 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001613 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001614 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001615 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001616 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617
Willy Tarreau977b8e42006-12-29 14:19:17 +01001618 if (!strcmp(args[0], "listen"))
1619 rc = PR_CAP_LISTEN;
1620 else if (!strcmp(args[0], "frontend"))
1621 rc = PR_CAP_FE | PR_CAP_RS;
1622 else if (!strcmp(args[0], "backend"))
1623 rc = PR_CAP_BE | PR_CAP_RS;
1624 else if (!strcmp(args[0], "ruleset"))
1625 rc = PR_CAP_RS;
1626 else
1627 rc = PR_CAP_NONE;
1628
1629 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 if (!*args[1]) {
1631 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1632 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1633 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_ALERT | ERR_ABORT;
1635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001637
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001638 err = invalid_char(args[1]);
1639 if (err) {
1640 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1641 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001643 }
1644
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001645 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1646 /*
1647 * If there are two proxies with the same name only following
1648 * combinations are allowed:
1649 *
1650 * listen backend frontend ruleset
1651 * listen - - - -
1652 * backend - - OK -
1653 * frontend - OK - -
1654 * ruleset - - - -
1655 */
1656
1657 if (!strcmp(curproxy->id, args[1]) &&
1658 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1659 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001660 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1661 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1662 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001664 }
1665 }
1666
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1668 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_ALERT | ERR_ABORT;
1670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001672
Willy Tarreau97cb7802010-01-03 20:23:58 +01001673 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001674 curproxy->next = proxy;
1675 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001676 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001677 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001678 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001680 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001681
1682 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001684 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001685 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001686
Willy Tarreau4348fad2012-09-20 16:48:07 +02001687 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1688
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001689 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1690 if (err_msg && *err_msg) {
1691 indent_msg(&err_msg, 2);
1692 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1693 }
1694 else
1695 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1696 file, linenum, args[0], args[1], args[2]);
1697 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001698 err_code |= ERR_FATAL;
1699 goto out;
1700 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001701
Willy Tarreau4348fad2012-09-20 16:48:07 +02001702 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001703 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001705 }
1706
1707 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001708 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001709 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001710
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001713 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001714 curproxy->no_options = defproxy.no_options;
1715 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001716 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001717 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001718 curproxy->except_net = defproxy.except_net;
1719 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001720 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001721 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001723 if (defproxy.fwdfor_hdr_len) {
1724 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1725 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1726 }
1727
Willy Tarreaub86db342009-11-30 11:50:16 +01001728 if (defproxy.orgto_hdr_len) {
1729 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1730 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1731 }
1732
Mark Lamourinec2247f02012-01-04 13:02:01 -05001733 if (defproxy.server_id_hdr_len) {
1734 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1735 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1736 }
1737
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 if (curproxy->cap & PR_CAP_FE) {
1739 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001740 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001741 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001742
1743 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001744 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1745 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001746
1747 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749
Willy Tarreau977b8e42006-12-29 14:19:17 +01001750 if (curproxy->cap & PR_CAP_BE) {
1751 curproxy->fullconn = defproxy.fullconn;
1752 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001754 if (defproxy.check_req) {
1755 curproxy->check_req = calloc(1, defproxy.check_len);
1756 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1757 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001758 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001760 if (defproxy.expect_str) {
1761 curproxy->expect_str = strdup(defproxy.expect_str);
1762 if (defproxy.expect_regex) {
1763 /* note: this regex is known to be valid */
1764 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1765 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1766 }
1767 }
1768
Willy Tarreau67402132012-05-31 20:40:20 +02001769 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001770 if (defproxy.cookie_name)
1771 curproxy->cookie_name = strdup(defproxy.cookie_name);
1772 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001773 if (defproxy.cookie_domain)
1774 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001775
Willy Tarreau31936852010-10-06 16:59:56 +02001776 if (defproxy.cookie_maxidle)
1777 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1778
1779 if (defproxy.cookie_maxlife)
1780 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1781
Emeric Brun647caf12009-06-30 17:57:00 +02001782 if (defproxy.rdp_cookie_name)
1783 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1784 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1785
Willy Tarreau01732802007-11-01 22:48:15 +01001786 if (defproxy.url_param_name)
1787 curproxy->url_param_name = strdup(defproxy.url_param_name);
1788 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001789
Benoitaffb4812009-03-25 13:02:10 +01001790 if (defproxy.hh_name)
1791 curproxy->hh_name = strdup(defproxy.hh_name);
1792 curproxy->hh_len = defproxy.hh_len;
1793 curproxy->hh_match_domain = defproxy.hh_match_domain;
1794
Willy Tarreauef9a3602012-12-08 22:29:20 +01001795 if (defproxy.conn_src.iface_name)
1796 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1797 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
1798 curproxy->conn_src.opts = defproxy.conn_src.opts & ~CO_SRC_TPROXY_MASK;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001801 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001802 if (defproxy.capture_name)
1803 curproxy->capture_name = strdup(defproxy.capture_name);
1804 curproxy->capture_namelen = defproxy.capture_namelen;
1805 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807
Willy Tarreau977b8e42006-12-29 14:19:17 +01001808 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001809 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001810 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001811 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001812 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001813 curproxy->uri_auth = defproxy.uri_auth;
1814 curproxy->mon_net = defproxy.mon_net;
1815 curproxy->mon_mask = defproxy.mon_mask;
1816 if (defproxy.monitor_uri)
1817 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1818 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001819 if (defproxy.defbe.name)
1820 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001821
1822 /* get either a pointer to the logformat string or a copy of it */
1823 curproxy->logformat_string = defproxy.logformat_string;
1824 if (curproxy->logformat_string &&
1825 curproxy->logformat_string != default_http_log_format &&
1826 curproxy->logformat_string != default_tcp_log_format &&
1827 curproxy->logformat_string != clf_http_log_format)
1828 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001829 }
1830
1831 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001832 curproxy->timeout.connect = defproxy.timeout.connect;
1833 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001834 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001835 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001836 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001837 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001838 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001839 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001840 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 }
1842
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001844
1845 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001846 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001847 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001848 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001849 LIST_INIT(&node->list);
1850 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1851 }
1852
Willy Tarreau196729e2012-05-31 19:30:26 +02001853 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1854 if (curproxy->uniqueid_format_string)
1855 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001856
1857 /* copy default header unique id */
1858 if (defproxy.header_unique_id)
1859 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1860
William Lallemand82fe75c2012-10-23 10:25:10 +02001861 /* default compression options */
1862 if (defproxy.comp != NULL) {
1863 curproxy->comp = calloc(1, sizeof(struct comp));
1864 curproxy->comp->algos = defproxy.comp->algos;
1865 curproxy->comp->types = defproxy.comp->types;
1866 }
1867
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001869 curproxy->conf.used_listener_id = EB_ROOT;
1870 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001871
Willy Tarreau93893792009-07-23 13:19:11 +02001872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 }
1874 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1875 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001876 /* FIXME-20070101: we should do this too at the end of the
1877 * config parsing to free all default values.
1878 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001879 free(defproxy.check_req);
1880 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001881 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001882 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001883 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001884 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001885 free(defproxy.capture_name);
1886 free(defproxy.monitor_uri);
1887 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001888 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001889 free(defproxy.fwdfor_hdr_name);
1890 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001891 free(defproxy.orgto_hdr_name);
1892 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001893 free(defproxy.server_id_hdr_name);
1894 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001895 free(defproxy.expect_str);
1896 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001897
Willy Tarreau39b06652012-06-01 10:58:06 +02001898 if (defproxy.logformat_string != default_http_log_format &&
1899 defproxy.logformat_string != default_tcp_log_format &&
1900 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001901 free(defproxy.logformat_string);
1902
1903 free(defproxy.uniqueid_format_string);
1904
Willy Tarreaua534fea2008-08-03 12:19:50 +02001905 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001906 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001907
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 /* we cannot free uri_auth because it might already be used */
1909 init_default_instance();
1910 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914 else if (curproxy == NULL) {
1915 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 }
1919
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920
1921 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001923 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001924 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001925 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001926
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934
Emeric Bruned760922010-10-22 17:59:25 +02001935 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001936 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001941
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001942 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01001943
1944 /* use default settings for unix sockets */
1945 bind_conf->ux.uid = global.unix_bind.ux.uid;
1946 bind_conf->ux.gid = global.unix_bind.ux.gid;
1947 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02001948
1949 /* NOTE: the following line might create several listeners if there
1950 * are comma-separated IPs or port ranges. So all further processing
1951 * will have to be applied to all listeners created after last_listen.
1952 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001953 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1954 if (err_msg && *err_msg) {
1955 indent_msg(&err_msg, 2);
1956 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1957 }
1958 else
1959 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1960 file, linenum, args[0], args[1]);
1961 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
1964 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001965
Willy Tarreau4348fad2012-09-20 16:48:07 +02001966 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1967 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001968 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001969 }
1970
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001971 cur_arg = 2;
1972 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001973 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001974 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001975 char *err;
1976
Willy Tarreau26982662012-09-12 23:17:10 +02001977 kw = bind_find_kw(args[cur_arg]);
1978 if (kw) {
1979 char *err = NULL;
1980 int code;
1981
1982 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001983 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001985 cur_arg += 1 + kw->skip ;
1986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
1988 }
1989
Willy Tarreau4348fad2012-09-20 16:48:07 +02001990 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001991 err_code |= code;
1992
1993 if (code) {
1994 if (err && *err) {
1995 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001996 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001997 }
1998 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001999 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2000 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002001 if (code & ERR_FATAL) {
2002 free(err);
2003 cur_arg += 1 + kw->skip;
2004 goto out;
2005 }
2006 }
2007 free(err);
2008 cur_arg += 1 + kw->skip;
2009 continue;
2010 }
2011
Willy Tarreau8638f482012-09-18 18:01:17 +02002012 err = NULL;
2013 if (!bind_dumped) {
2014 bind_dump_kws(&err);
2015 indent_msg(&err, 4);
2016 bind_dumped = 1;
2017 }
2018
2019 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2020 file, linenum, args[0], args[1], args[cur_arg],
2021 err ? " Registered keywords :" : "", err ? err : "");
2022 free(err);
2023
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002026 }
Willy Tarreau93893792009-07-23 13:19:11 +02002027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 }
2029 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2030 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2031 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2032 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002036 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002037 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002038
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 /* flush useless bits */
2040 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002042 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002043 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046
Willy Tarreau1c47f852006-07-09 08:22:27 +02002047 if (!*args[1]) {
2048 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002050 err_code |= ERR_ALERT | ERR_FATAL;
2051 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002052 }
2053
Willy Tarreaua534fea2008-08-03 12:19:50 +02002054 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002055 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002056 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002057 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002058 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2059
Willy Tarreau93893792009-07-23 13:19:11 +02002060 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2063 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2064 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2065 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2066 else {
2067 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 }
2071 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002072 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002073 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002074
2075 if (curproxy == &defproxy) {
2076 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2077 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002080 }
2081
2082 if (!*args[1]) {
2083 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2084 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002085 err_code |= ERR_ALERT | ERR_FATAL;
2086 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002087 }
2088
2089 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002090 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002091
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002092 if (curproxy->uuid <= 0) {
2093 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002094 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002097 }
2098
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002099 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2100 if (node) {
2101 struct proxy *target = container_of(node, struct proxy, conf.id);
2102 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2103 file, linenum, proxy_type_str(curproxy), curproxy->id,
2104 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
2108 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002109 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002110 else if (!strcmp(args[0], "description")) {
2111 int i, len=0;
2112 char *d;
2113
Cyril Bonté99ed3272010-01-24 23:29:44 +01002114 if (curproxy == &defproxy) {
2115 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2116 file, linenum, args[0]);
2117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
2119 }
2120
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002121 if (!*args[1]) {
2122 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2123 file, linenum, args[0]);
2124 return -1;
2125 }
2126
2127 for(i=1; *args[i]; i++)
2128 len += strlen(args[i])+1;
2129
2130 d = (char *)calloc(1, len);
2131 curproxy->desc = d;
2132
2133 d += sprintf(d, "%s", args[1]);
2134 for(i=2; *args[i]; i++)
2135 d += sprintf(d, " %s", args[i]);
2136
2137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2139 curproxy->state = PR_STSTOPPED;
2140 }
2141 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2142 curproxy->state = PR_STNEW;
2143 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002144 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2145 int cur_arg = 1;
2146 unsigned int set = 0;
2147
2148 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002149 unsigned int low, high;
2150
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002151 if (strcmp(args[cur_arg], "all") == 0) {
2152 set = 0;
2153 break;
2154 }
2155 else if (strcmp(args[cur_arg], "odd") == 0) {
2156 set |= 0x55555555;
2157 }
2158 else if (strcmp(args[cur_arg], "even") == 0) {
2159 set |= 0xAAAAAAAA;
2160 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002161 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002162 char *dash = strchr(args[cur_arg], '-');
2163
2164 low = high = str2uic(args[cur_arg]);
2165 if (dash)
2166 high = str2uic(dash + 1);
2167
2168 if (high < low) {
2169 unsigned int swap = low;
2170 low = high;
2171 high = swap;
2172 }
2173
2174 if (low < 1 || high > 32) {
2175 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002176 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002179 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002180
2181 if (high > global.nbproc) {
2182 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2183 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002185 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002186 while (low <= high)
2187 set |= 1 << (low++ - 1);
2188 }
2189 else {
2190 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2191 file, linenum, args[0]);
2192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002194 }
2195 cur_arg++;
2196 }
2197 curproxy->bind_proc = set;
2198 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002199 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002200 if (curproxy == &defproxy) {
2201 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002204 }
2205
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002206 err = invalid_char(args[1]);
2207 if (err) {
2208 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2209 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002211 }
2212
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002213 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2214 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2215 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002218 }
2219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2221 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222
Willy Tarreau977b8e42006-12-29 14:19:17 +01002223 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 if (*(args[1]) == 0) {
2227 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2228 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002232
Willy Tarreau67402132012-05-31 20:40:20 +02002233 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002234 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002235 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002236 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 curproxy->cookie_name = strdup(args[1]);
2238 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 cur_arg = 2;
2241 while (*(args[cur_arg])) {
2242 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 }
2245 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002246 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
2248 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002249 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
2251 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002252 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 }
2254 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002255 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002257 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002258 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002261 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002263 else if (!strcmp(args[cur_arg], "httponly")) {
2264 curproxy->ck_opts |= PR_CK_HTTPONLY;
2265 }
2266 else if (!strcmp(args[cur_arg], "secure")) {
2267 curproxy->ck_opts |= PR_CK_SECURE;
2268 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002269 else if (!strcmp(args[cur_arg], "domain")) {
2270 if (!*args[cur_arg + 1]) {
2271 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2272 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002275 }
2276
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002277 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002278 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002279 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2280 " dots nor does not start with a dot."
2281 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002282 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002283 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002284 }
2285
2286 err = invalid_domainchar(args[cur_arg + 1]);
2287 if (err) {
2288 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2289 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002292 }
2293
Willy Tarreau68a897b2009-12-03 23:28:34 +01002294 if (!curproxy->cookie_domain) {
2295 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2296 } else {
2297 /* one domain was already specified, add another one by
2298 * building the string which will be returned along with
2299 * the cookie.
2300 */
2301 char *new_ptr;
2302 int new_len = strlen(curproxy->cookie_domain) +
2303 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2304 new_ptr = malloc(new_len);
2305 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2306 free(curproxy->cookie_domain);
2307 curproxy->cookie_domain = new_ptr;
2308 }
Willy Tarreau31936852010-10-06 16:59:56 +02002309 cur_arg++;
2310 }
2311 else if (!strcmp(args[cur_arg], "maxidle")) {
2312 unsigned int maxidle;
2313 const char *res;
2314
2315 if (!*args[cur_arg + 1]) {
2316 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2317 file, linenum, args[cur_arg]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321
2322 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2323 if (res) {
2324 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2325 file, linenum, *res, args[cur_arg]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329 curproxy->cookie_maxidle = maxidle;
2330 cur_arg++;
2331 }
2332 else if (!strcmp(args[cur_arg], "maxlife")) {
2333 unsigned int maxlife;
2334 const char *res;
2335
2336 if (!*args[cur_arg + 1]) {
2337 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2338 file, linenum, args[cur_arg]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342
2343 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2344 if (res) {
2345 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2346 file, linenum, *res, args[cur_arg]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002351 cur_arg++;
2352 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002354 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 +02002355 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
2359 cur_arg++;
2360 }
Willy Tarreau67402132012-05-31 20:40:20 +02002361 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2363 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002364 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
2366
Willy Tarreau67402132012-05-31 20:40:20 +02002367 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2369 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002372
Willy Tarreau67402132012-05-31 20:40:20 +02002373 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002374 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2375 file, linenum);
2376 err_code |= ERR_ALERT | ERR_FATAL;
2377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002379 else if (!strcmp(args[0], "persist")) { /* persist */
2380 if (*(args[1]) == 0) {
2381 Alert("parsing [%s:%d] : missing persist method.\n",
2382 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002385 }
2386
2387 if (!strncmp(args[1], "rdp-cookie", 10)) {
2388 curproxy->options2 |= PR_O2_RDPC_PRST;
2389
Emeric Brunb982a3d2010-01-04 15:45:53 +01002390 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002391 const char *beg, *end;
2392
2393 beg = args[1] + 11;
2394 end = strchr(beg, ')');
2395
2396 if (!end || end == beg) {
2397 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2398 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002401 }
2402
2403 free(curproxy->rdp_cookie_name);
2404 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2405 curproxy->rdp_cookie_len = end-beg;
2406 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002407 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002408 free(curproxy->rdp_cookie_name);
2409 curproxy->rdp_cookie_name = strdup("msts");
2410 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2411 }
2412 else { /* syntax */
2413 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2414 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002417 }
2418 }
2419 else {
2420 Alert("parsing [%s:%d] : unknown persist method.\n",
2421 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002424 }
2425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002427 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002429 if (curproxy == &defproxy) {
2430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
2433 }
2434
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002439 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
2444 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002445 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 curproxy->appsession_name = strdup(args[1]);
2447 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2448 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002449 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2450 if (err) {
2451 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2452 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002455 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002456 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002457
Willy Tarreau51041c72007-09-09 21:56:53 +02002458 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2459 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002460 err_code |= ERR_ALERT | ERR_ABORT;
2461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002463
2464 cur_arg = 6;
2465 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002466 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2467 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002468 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002469 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002470 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002471 } else if (!strcmp(args[cur_arg], "prefix")) {
2472 curproxy->options2 |= PR_O2_AS_PFX;
2473 } else if (!strcmp(args[cur_arg], "mode")) {
2474 if (!*args[cur_arg + 1]) {
2475 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2476 file, linenum, args[0], args[cur_arg]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
2481 cur_arg++;
2482 if (!strcmp(args[cur_arg], "query-string")) {
2483 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2484 curproxy->options2 |= PR_O2_AS_M_QS;
2485 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2486 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2487 curproxy->options2 |= PR_O2_AS_M_PP;
2488 } else {
2489 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002494 cur_arg++;
2495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 } /* Url App Session */
2497 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002498 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002500
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002502 if (curproxy == &defproxy) {
2503 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507
Willy Tarreaubaaee002006-06-26 02:48:02 +02002508 if (*(args[4]) == 0) {
2509 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002513 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002514 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002515 curproxy->capture_name = strdup(args[2]);
2516 curproxy->capture_namelen = strlen(curproxy->capture_name);
2517 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 curproxy->to_log |= LW_COOKIE;
2519 }
2520 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2521 struct cap_hdr *hdr;
2522
2523 if (curproxy == &defproxy) {
2524 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 +02002525 err_code |= ERR_ALERT | ERR_FATAL;
2526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 }
2528
2529 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2530 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2531 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 }
2535
2536 hdr = calloc(sizeof(struct cap_hdr), 1);
2537 hdr->next = curproxy->req_cap;
2538 hdr->name = strdup(args[3]);
2539 hdr->namelen = strlen(args[3]);
2540 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002541 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 hdr->index = curproxy->nb_req_cap++;
2543 curproxy->req_cap = hdr;
2544 curproxy->to_log |= LW_REQHDR;
2545 }
2546 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2547 struct cap_hdr *hdr;
2548
2549 if (curproxy == &defproxy) {
2550 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 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554
2555 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2556 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2557 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
2561 hdr = calloc(sizeof(struct cap_hdr), 1);
2562 hdr->next = curproxy->rsp_cap;
2563 hdr->name = strdup(args[3]);
2564 hdr->namelen = strlen(args[3]);
2565 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002566 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 hdr->index = curproxy->nb_rsp_cap++;
2568 curproxy->rsp_cap = hdr;
2569 curproxy->to_log |= LW_RSPHDR;
2570 }
2571 else {
2572 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 if (*(args[1]) == 0) {
2583 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2584 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
2588 curproxy->conn_retries = atol(args[1]);
2589 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002590 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002591 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002592
2593 if (curproxy == &defproxy) {
2594 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
Willy Tarreau20b0de52012-12-24 15:45:22 +01002599 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2600 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2601 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2602 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
2603 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2604 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 +01002605 file, linenum, args[0]);
2606 err_code |= ERR_WARN;
2607 }
2608
Willy Tarreauff011f22011-01-06 17:51:27 +01002609 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002610
Willy Tarreauff011f22011-01-06 17:51:27 +01002611 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002612 err_code |= ERR_ALERT | ERR_ABORT;
2613 goto out;
2614 }
2615
Willy Tarreauff011f22011-01-06 17:51:27 +01002616 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2617 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002618 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002619 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2620 /* set the header name and length into the proxy structure */
2621 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2622 err_code |= ERR_WARN;
2623
2624 if (!*args[1]) {
2625 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2626 file, linenum, args[0]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
2630
2631 /* set the desired header name */
2632 free(curproxy->server_id_hdr_name);
2633 curproxy->server_id_hdr_name = strdup(args[1]);
2634 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2635 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002636 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002637 if (curproxy == &defproxy) {
2638 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002641 }
2642
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002644 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2645 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002648 }
2649
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002650 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2651 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2652 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002655 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002656
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002657 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002658 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002659 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002662
Cyril Bonté99ed3272010-01-24 23:29:44 +01002663 if (curproxy == &defproxy) {
2664 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
Willy Tarreau4baae242012-12-27 12:00:31 +01002669 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2670 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2671 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002674 }
2675
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002676 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002677 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2678 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002680 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002681 struct switching_rule *rule;
2682
Willy Tarreaub099aca2008-10-12 17:26:37 +02002683 if (curproxy == &defproxy) {
2684 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002687 }
2688
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691
2692 if (*(args[1]) == 0) {
2693 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002696 }
2697
Willy Tarreauef6494c2010-01-28 17:12:36 +01002698 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2700 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002703 }
2704
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002705 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2706 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2707 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002710 }
2711
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002712 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002713
Willy Tarreau55ea7572007-06-17 19:56:27 +02002714 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2715 rule->cond = cond;
2716 rule->be.name = strdup(args[1]);
2717 LIST_INIT(&rule->list);
2718 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2719 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002720 else if (strcmp(args[0], "use-server") == 0) {
2721 struct server_rule *rule;
2722
2723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
2729 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2730 err_code |= ERR_WARN;
2731
2732 if (*(args[1]) == 0) {
2733 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737
2738 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2739 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2740 file, linenum, args[0]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002745 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2746 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2747 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
2750 }
2751
2752 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2753
2754 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2755 rule->cond = cond;
2756 rule->srv.name = strdup(args[1]);
2757 LIST_INIT(&rule->list);
2758 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2759 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2760 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002761 else if ((!strcmp(args[0], "force-persist")) ||
2762 (!strcmp(args[0], "ignore-persist"))) {
2763 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002764
2765 if (curproxy == &defproxy) {
2766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770
2771 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2772 err_code |= ERR_WARN;
2773
Willy Tarreauef6494c2010-01-28 17:12:36 +01002774 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002775 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2776 file, linenum, args[0]);
2777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
2779 }
2780
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002781 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2782 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2783 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
2786 }
2787
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002788 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002789
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002790 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002791 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002792 if (!strcmp(args[0], "force-persist")) {
2793 rule->type = PERSIST_TYPE_FORCE;
2794 } else {
2795 rule->type = PERSIST_TYPE_IGNORE;
2796 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002797 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002798 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002799 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002800 else if (!strcmp(args[0], "stick-table")) {
2801 int myidx = 1;
2802
Emeric Brun32da3c42010-09-23 18:39:19 +02002803 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002804 curproxy->table.type = (unsigned int)-1;
2805 while (*args[myidx]) {
2806 const char *err;
2807
2808 if (strcmp(args[myidx], "size") == 0) {
2809 myidx++;
2810 if (!*(args[myidx])) {
2811 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2812 file, linenum, args[myidx-1]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2817 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2818 file, linenum, *err, args[myidx-1]);
2819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
2821 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002822 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002823 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002824 else if (strcmp(args[myidx], "peers") == 0) {
2825 myidx++;
2826 if (!*(args[myidx])) {
2827 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2828 file, linenum, args[myidx-1]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832 curproxy->table.peers.name = strdup(args[myidx++]);
2833 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002834 else if (strcmp(args[myidx], "expire") == 0) {
2835 myidx++;
2836 if (!*(args[myidx])) {
2837 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2838 file, linenum, args[myidx-1]);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2843 if (err) {
2844 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2845 file, linenum, *err, args[myidx-1]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002850 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002851 }
2852 else if (strcmp(args[myidx], "nopurge") == 0) {
2853 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002854 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002855 }
2856 else if (strcmp(args[myidx], "type") == 0) {
2857 myidx++;
2858 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2859 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2860 file, linenum, args[myidx]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002864 /* myidx already points to next arg */
2865 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002866 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002867 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002868 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002869
2870 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002871 nw = args[myidx];
2872 while (*nw) {
2873 /* the "store" keyword supports a comma-separated list */
2874 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002875 sa = NULL; /* store arg */
2876 while (*nw && *nw != ',') {
2877 if (*nw == '(') {
2878 *nw = 0;
2879 sa = ++nw;
2880 while (*nw != ')') {
2881 if (!*nw) {
2882 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2883 file, linenum, args[0], cw);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887 nw++;
2888 }
2889 *nw = '\0';
2890 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002891 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002892 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002893 if (*nw)
2894 *nw++ = '\0';
2895 type = stktable_get_data_type(cw);
2896 if (type < 0) {
2897 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2898 file, linenum, args[0], cw);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
Willy Tarreauac782882010-06-20 10:41:54 +02002902
2903 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2904 switch (err) {
2905 case PE_NONE: break;
2906 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002907 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2908 file, linenum, args[0], cw);
2909 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002910 break;
2911
2912 case PE_ARG_MISSING:
2913 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2914 file, linenum, args[0], cw);
2915 err_code |= ERR_ALERT | ERR_FATAL;
2916 goto out;
2917
2918 case PE_ARG_NOT_USED:
2919 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2920 file, linenum, args[0], cw);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923
2924 default:
2925 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002929 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002930 }
2931 myidx++;
2932 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002933 else {
2934 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2935 file, linenum, args[myidx]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002939 }
2940
2941 if (!curproxy->table.size) {
2942 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2943 file, linenum);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946 }
2947
2948 if (curproxy->table.type == (unsigned int)-1) {
2949 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2950 file, linenum);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
2954 }
2955 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002957 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 int myidx = 0;
2959 const char *name = NULL;
2960 int flags;
2961
2962 if (curproxy == &defproxy) {
2963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967
2968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2969 err_code |= ERR_WARN;
2970 goto out;
2971 }
2972
2973 myidx++;
2974 if ((strcmp(args[myidx], "store") == 0) ||
2975 (strcmp(args[myidx], "store-request") == 0)) {
2976 myidx++;
2977 flags = STK_IS_STORE;
2978 }
2979 else if (strcmp(args[myidx], "store-response") == 0) {
2980 myidx++;
2981 flags = STK_IS_STORE | STK_ON_RSP;
2982 }
2983 else if (strcmp(args[myidx], "match") == 0) {
2984 myidx++;
2985 flags = STK_IS_MATCH;
2986 }
2987 else if (strcmp(args[myidx], "on") == 0) {
2988 myidx++;
2989 flags = STK_IS_MATCH | STK_IS_STORE;
2990 }
2991 else {
2992 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996
2997 if (*(args[myidx]) == 0) {
2998 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003003 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003005 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
3008 }
3009
3010 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003011 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003012 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3013 file, linenum, args[0], expr->fetch->kw);
3014 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003015 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003016 goto out;
3017 }
3018 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003019 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3021 file, linenum, args[0], expr->fetch->kw);
3022 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003023 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 goto out;
3025 }
3026 }
3027
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003028 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3029 if (expr->fetch->cap & SMP_CAP_L7)
3030 curproxy->acl_requires |= ACL_USE_L7_ANY;
3031
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 if (strcmp(args[myidx], "table") == 0) {
3033 myidx++;
3034 name = args[myidx++];
3035 }
3036
Willy Tarreauef6494c2010-01-28 17:12:36 +01003037 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003038 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3039 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3040 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003042 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 goto out;
3044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003046 else if (*(args[myidx])) {
3047 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3048 file, linenum, args[0], args[myidx]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003050 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003051 goto out;
3052 }
Emeric Brun97679e72010-09-23 17:56:44 +02003053 if (flags & STK_ON_RSP)
3054 err_code |= warnif_cond_requires_req(cond, file, linenum);
3055 else
3056 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003057
Emeric Brunb982a3d2010-01-04 15:45:53 +01003058 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3059 rule->cond = cond;
3060 rule->expr = expr;
3061 rule->flags = flags;
3062 rule->table.name = name ? strdup(name) : NULL;
3063 LIST_INIT(&rule->list);
3064 if (flags & STK_ON_RSP)
3065 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3066 else
3067 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003072
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3074 curproxy->uri_auth = NULL; /* we must detach from the default config */
3075
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003076 if (!*args[1]) {
3077 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003078 } else if (!strcmp(args[1], "admin")) {
3079 struct stats_admin_rule *rule;
3080
3081 if (curproxy == &defproxy) {
3082 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
3087 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3088 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3089 err_code |= ERR_ALERT | ERR_ABORT;
3090 goto out;
3091 }
3092
3093 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3094 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3095 file, linenum, args[0], args[1]);
3096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
3098 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003099 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3100 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3101 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105
3106 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3107
3108 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3109 rule->cond = cond;
3110 LIST_INIT(&rule->list);
3111 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 } else if (!strcmp(args[1], "uri")) {
3113 if (*(args[2]) == 0) {
3114 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_ABORT;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 }
3122 } else if (!strcmp(args[1], "realm")) {
3123 if (*(args[2]) == 0) {
3124 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003132 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003133 unsigned interval;
3134
3135 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3136 if (err) {
3137 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3138 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003141 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003145 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003147 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003148
3149 if (curproxy == &defproxy) {
3150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154
3155 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3156 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3157 err_code |= ERR_ALERT | ERR_ABORT;
3158 goto out;
3159 }
3160
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3162 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003163 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3164 file, linenum, args[0]);
3165 err_code |= ERR_WARN;
3166 }
3167
Willy Tarreauff011f22011-01-06 17:51:27 +01003168 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169
Willy Tarreauff011f22011-01-06 17:51:27 +01003170 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
3173 }
3174
Willy Tarreauff011f22011-01-06 17:51:27 +01003175 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3176 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 } else if (!strcmp(args[1], "auth")) {
3179 if (*(args[2]) == 0) {
3180 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_FATAL;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003185 err_code |= ERR_ALERT | ERR_ABORT;
3186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
3188 } else if (!strcmp(args[1], "scope")) {
3189 if (*(args[2]) == 0) {
3190 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 }
3198 } else if (!strcmp(args[1], "enable")) {
3199 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3200 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_ABORT;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003204 } else if (!strcmp(args[1], "hide-version")) {
3205 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3206 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003207 err_code |= ERR_ALERT | ERR_ABORT;
3208 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003209 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003210 } else if (!strcmp(args[1], "show-legends")) {
3211 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3212 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3213 err_code |= ERR_ALERT | ERR_ABORT;
3214 goto out;
3215 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003216 } else if (!strcmp(args[1], "show-node")) {
3217
3218 if (*args[2]) {
3219 int i;
3220 char c;
3221
3222 for (i=0; args[2][i]; i++) {
3223 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003224 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3225 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003226 break;
3227 }
3228
3229 if (!i || args[2][i]) {
3230 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3231 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3232 file, linenum, args[0], args[1]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236 }
3237
3238 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3239 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3240 err_code |= ERR_ALERT | ERR_ABORT;
3241 goto out;
3242 }
3243 } else if (!strcmp(args[1], "show-desc")) {
3244 char *desc = NULL;
3245
3246 if (*args[2]) {
3247 int i, len=0;
3248 char *d;
3249
3250 for(i=2; *args[i]; i++)
3251 len += strlen(args[i])+1;
3252
3253 desc = d = (char *)calloc(1, len);
3254
3255 d += sprintf(d, "%s", args[2]);
3256 for(i=3; *args[i]; i++)
3257 d += sprintf(d, " %s", args[i]);
3258 }
3259
3260 if (!*args[2] && !global.desc)
3261 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3262 file, linenum, args[1]);
3263 else {
3264 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3265 free(desc);
3266 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3267 err_code |= ERR_ALERT | ERR_ABORT;
3268 goto out;
3269 }
3270 free(desc);
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003273stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003274 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 +01003275 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279 }
3280 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003281 int optnum;
3282
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003283 if (*(args[1]) == '\0') {
3284 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_ALERT | ERR_FATAL;
3287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003289
3290 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3291 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003292 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3293 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3294 file, linenum, cfg_opts[optnum].name);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
Willy Tarreau93893792009-07-23 13:19:11 +02003298 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3299 err_code |= ERR_WARN;
3300 goto out;
3301 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003302
Willy Tarreau3842f002009-06-14 11:39:52 +02003303 curproxy->no_options &= ~cfg_opts[optnum].val;
3304 curproxy->options &= ~cfg_opts[optnum].val;
3305
3306 switch (kwm) {
3307 case KWM_STD:
3308 curproxy->options |= cfg_opts[optnum].val;
3309 break;
3310 case KWM_NO:
3311 curproxy->no_options |= cfg_opts[optnum].val;
3312 break;
3313 case KWM_DEF: /* already cleared */
3314 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003315 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003316
Willy Tarreau93893792009-07-23 13:19:11 +02003317 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318 }
3319 }
3320
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003321 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3322 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003323 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3324 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3325 file, linenum, cfg_opts2[optnum].name);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
Willy Tarreau93893792009-07-23 13:19:11 +02003329 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3330 err_code |= ERR_WARN;
3331 goto out;
3332 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003333
Willy Tarreau3842f002009-06-14 11:39:52 +02003334 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3335 curproxy->options2 &= ~cfg_opts2[optnum].val;
3336
3337 switch (kwm) {
3338 case KWM_STD:
3339 curproxy->options2 |= cfg_opts2[optnum].val;
3340 break;
3341 case KWM_NO:
3342 curproxy->no_options2 |= cfg_opts2[optnum].val;
3343 break;
3344 case KWM_DEF: /* already cleared */
3345 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003346 }
Willy Tarreau93893792009-07-23 13:19:11 +02003347 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003348 }
3349 }
3350
Willy Tarreau3842f002009-06-14 11:39:52 +02003351 if (kwm != KWM_STD) {
3352 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003353 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003356 }
3357
Emeric Brun3a058f32009-06-30 18:26:00 +02003358 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003359 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003361 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003362 if (*(args[2]) != '\0') {
3363 if (!strcmp(args[2], "clf")) {
3364 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003365 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 } else {
3367 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003368 err_code |= ERR_ALERT | ERR_FATAL;
3369 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003370 }
3371 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003372 if (curproxy->logformat_string != default_http_log_format &&
3373 curproxy->logformat_string != default_tcp_log_format &&
3374 curproxy->logformat_string != clf_http_log_format)
3375 free(curproxy->logformat_string);
3376 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003377 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003378 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003380 if (curproxy->logformat_string != default_http_log_format &&
3381 curproxy->logformat_string != default_tcp_log_format &&
3382 curproxy->logformat_string != clf_http_log_format)
3383 free(curproxy->logformat_string);
3384 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 else if (!strcmp(args[1], "tcpka")) {
3387 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003388 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003390
3391 if (curproxy->cap & PR_CAP_FE)
3392 curproxy->options |= PR_O_TCP_CLI_KA;
3393 if (curproxy->cap & PR_CAP_BE)
3394 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
3396 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_WARN;
3399
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003401 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003402 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003403 curproxy->options2 &= ~PR_O2_CHK_ANY;
3404 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 if (!*args[2]) { /* no argument */
3406 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3407 curproxy->check_len = strlen(DEF_CHECK_REQ);
3408 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003409 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 curproxy->check_req = (char *)malloc(reqlen);
3411 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003412 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003414 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 if (*args[4])
3416 reqlen += strlen(args[4]);
3417 else
3418 reqlen += strlen("HTTP/1.0");
3419
3420 curproxy->check_req = (char *)malloc(reqlen);
3421 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003422 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003424 }
3425 else if (!strcmp(args[1], "ssl-hello-chk")) {
3426 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003429
Willy Tarreaua534fea2008-08-03 12:19:50 +02003430 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003431 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003432 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003433 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Willy Tarreau23677902007-05-08 23:50:35 +02003435 else if (!strcmp(args[1], "smtpchk")) {
3436 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003437 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003438 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003439 curproxy->options2 &= ~PR_O2_CHK_ANY;
3440 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003441
3442 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3443 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3444 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3445 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3446 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3447 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3448 curproxy->check_req = (char *)malloc(reqlen);
3449 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3450 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3451 } else {
3452 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3453 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3454 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3455 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3456 }
3457 }
3458 }
Simon Hormana2b9dad2013-02-12 10:45:54 +09003459 else if (!strcmp(args[1], "lb-agent-chk")) {
3460 /* use dynmaic health check */
3461 free(curproxy->check_req);
3462 curproxy->check_req = NULL;
3463 curproxy->options2 &= ~PR_O2_CHK_ANY;
3464 curproxy->options2 |= PR_O2_LB_AGENT_CHK;
3465 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003466 else if (!strcmp(args[1], "pgsql-check")) {
3467 /* use PostgreSQL request to check servers' health */
3468 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3469 err_code |= ERR_WARN;
3470
3471 free(curproxy->check_req);
3472 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003473 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003474 curproxy->options2 |= PR_O2_PGSQL_CHK;
3475
3476 if (*(args[2])) {
3477 int cur_arg = 2;
3478
3479 while (*(args[cur_arg])) {
3480 if (strcmp(args[cur_arg], "user") == 0) {
3481 char * packet;
3482 uint32_t packet_len;
3483 uint32_t pv;
3484
3485 /* suboption header - needs additional argument for it */
3486 if (*(args[cur_arg+1]) == 0) {
3487 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3488 file, linenum, args[0], args[1], args[cur_arg]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492
3493 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3494 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3495 pv = htonl(0x30000); /* protocol version 3.0 */
3496
3497 packet = (char*) calloc(1, packet_len);
3498
3499 memcpy(packet + 4, &pv, 4);
3500
3501 /* copy "user" */
3502 memcpy(packet + 8, "user", 4);
3503
3504 /* copy username */
3505 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3506
3507 free(curproxy->check_req);
3508 curproxy->check_req = packet;
3509 curproxy->check_len = packet_len;
3510
3511 packet_len = htonl(packet_len);
3512 memcpy(packet, &packet_len, 4);
3513 cur_arg += 2;
3514 } else {
3515 /* unknown suboption - catchall */
3516 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3517 file, linenum, args[0], args[1]);
3518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
3520 }
3521 } /* end while loop */
3522 }
3523 }
3524
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003525 else if (!strcmp(args[1], "redis-check")) {
3526 /* use REDIS PING request to check servers' health */
3527 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3528 err_code |= ERR_WARN;
3529
3530 free(curproxy->check_req);
3531 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003532 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003533 curproxy->options2 |= PR_O2_REDIS_CHK;
3534
3535 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3536 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3537 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3538 }
3539
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003540 else if (!strcmp(args[1], "mysql-check")) {
3541 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003542 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3543 err_code |= ERR_WARN;
3544
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003545 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003546 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003547 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003548 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003549
3550 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3551 * const char mysql40_client_auth_pkt[] = {
3552 * "\x0e\x00\x00" // packet length
3553 * "\x01" // packet number
3554 * "\x00\x00" // client capabilities
3555 * "\x00\x00\x01" // max packet
3556 * "haproxy\x00" // username (null terminated string)
3557 * "\x00" // filler (always 0x00)
3558 * "\x01\x00\x00" // packet length
3559 * "\x00" // packet number
3560 * "\x01" // COM_QUIT command
3561 * };
3562 */
3563
3564 if (*(args[2])) {
3565 int cur_arg = 2;
3566
3567 while (*(args[cur_arg])) {
3568 if (strcmp(args[cur_arg], "user") == 0) {
3569 char *mysqluser;
3570 int packetlen, reqlen, userlen;
3571
3572 /* suboption header - needs additional argument for it */
3573 if (*(args[cur_arg+1]) == 0) {
3574 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3575 file, linenum, args[0], args[1], args[cur_arg]);
3576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
3578 }
3579 mysqluser = args[cur_arg + 1];
3580 userlen = strlen(mysqluser);
3581 packetlen = userlen + 7;
3582 reqlen = packetlen + 9;
3583
3584 free(curproxy->check_req);
3585 curproxy->check_req = (char *)calloc(1, reqlen);
3586 curproxy->check_len = reqlen;
3587
3588 snprintf(curproxy->check_req, 4, "%c%c%c",
3589 ((unsigned char) packetlen & 0xff),
3590 ((unsigned char) (packetlen >> 8) & 0xff),
3591 ((unsigned char) (packetlen >> 16) & 0xff));
3592
3593 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003594 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003595 curproxy->check_req[8] = 1;
3596 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3597 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3598 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3599 cur_arg += 2;
3600 } else {
3601 /* unknown suboption - catchall */
3602 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3603 file, linenum, args[0], args[1]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 } /* end while loop */
3608 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003609 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003610 else if (!strcmp(args[1], "ldap-check")) {
3611 /* use LDAP request to check servers' health */
3612 free(curproxy->check_req);
3613 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003614 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003615 curproxy->options2 |= PR_O2_LDAP_CHK;
3616
3617 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3618 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3619 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3620 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003621 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003622 int cur_arg;
3623
3624 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3625 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003626 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003627
Willy Tarreau87cf5142011-08-19 22:57:24 +02003628 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003629
3630 free(curproxy->fwdfor_hdr_name);
3631 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3632 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3633
3634 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3635 cur_arg = 2;
3636 while (*(args[cur_arg])) {
3637 if (!strcmp(args[cur_arg], "except")) {
3638 /* suboption except - needs additional argument for it */
3639 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3640 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3641 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003644 }
3645 /* flush useless bits */
3646 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003647 cur_arg += 2;
3648 } else if (!strcmp(args[cur_arg], "header")) {
3649 /* suboption header - needs additional argument for it */
3650 if (*(args[cur_arg+1]) == 0) {
3651 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3652 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003655 }
3656 free(curproxy->fwdfor_hdr_name);
3657 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3658 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3659 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003660 } else if (!strcmp(args[cur_arg], "if-none")) {
3661 curproxy->options &= ~PR_O_FF_ALWAYS;
3662 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003663 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003664 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003665 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003669 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003670 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003671 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003672 else if (!strcmp(args[1], "originalto")) {
3673 int cur_arg;
3674
3675 /* insert x-original-to field, but not for the IP address listed as an except.
3676 * set default options (ie: bitfield, header name, etc)
3677 */
3678
3679 curproxy->options |= PR_O_ORGTO;
3680
3681 free(curproxy->orgto_hdr_name);
3682 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3683 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3684
Willy Tarreau87cf5142011-08-19 22:57:24 +02003685 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003686 cur_arg = 2;
3687 while (*(args[cur_arg])) {
3688 if (!strcmp(args[cur_arg], "except")) {
3689 /* suboption except - needs additional argument for it */
3690 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3691 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3692 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003695 }
3696 /* flush useless bits */
3697 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3698 cur_arg += 2;
3699 } else if (!strcmp(args[cur_arg], "header")) {
3700 /* suboption header - needs additional argument for it */
3701 if (*(args[cur_arg+1]) == 0) {
3702 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3703 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003706 }
3707 free(curproxy->orgto_hdr_name);
3708 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3709 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3710 cur_arg += 2;
3711 } else {
3712 /* unknown suboption - catchall */
3713 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3714 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003717 }
3718 } /* end while loop */
3719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003720 else {
3721 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 }
Willy Tarreau93893792009-07-23 13:19:11 +02003725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003727 else if (!strcmp(args[0], "default_backend")) {
3728 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003730
3731 if (*(args[1]) == 0) {
3732 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003735 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003736 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003737 curproxy->defbe.name = strdup(args[1]);
3738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003739 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003740 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003742
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003743 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 /* enable reconnections to dispatch */
3747 curproxy->options |= PR_O_REDISP;
3748 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003749 else if (!strcmp(args[0], "http-check")) {
3750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003752
3753 if (strcmp(args[1], "disable-on-404") == 0) {
3754 /* enable a graceful server shutdown on an HTTP 404 response */
3755 curproxy->options |= PR_O_DISABLE404;
3756 }
Willy Tarreauef781042010-01-27 11:53:01 +01003757 else if (strcmp(args[1], "send-state") == 0) {
3758 /* enable emission of the apparent state of a server in HTTP checks */
3759 curproxy->options2 |= PR_O2_CHK_SNDST;
3760 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003761 else if (strcmp(args[1], "expect") == 0) {
3762 const char *ptr_arg;
3763 int cur_arg;
3764
3765 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3766 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
3769 }
3770
3771 cur_arg = 2;
3772 /* consider exclamation marks, sole or at the beginning of a word */
3773 while (*(ptr_arg = args[cur_arg])) {
3774 while (*ptr_arg == '!') {
3775 curproxy->options2 ^= PR_O2_EXP_INV;
3776 ptr_arg++;
3777 }
3778 if (*ptr_arg)
3779 break;
3780 cur_arg++;
3781 }
3782 /* now ptr_arg points to the beginning of a word past any possible
3783 * exclamation mark, and cur_arg is the argument which holds this word.
3784 */
3785 if (strcmp(ptr_arg, "status") == 0) {
3786 if (!*(args[cur_arg + 1])) {
3787 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3788 file, linenum, args[0], args[1], ptr_arg);
3789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
3791 }
3792 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003793 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003794 curproxy->expect_str = strdup(args[cur_arg + 1]);
3795 }
3796 else if (strcmp(ptr_arg, "string") == 0) {
3797 if (!*(args[cur_arg + 1])) {
3798 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3799 file, linenum, args[0], args[1], ptr_arg);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003804 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003805 curproxy->expect_str = strdup(args[cur_arg + 1]);
3806 }
3807 else if (strcmp(ptr_arg, "rstatus") == 0) {
3808 if (!*(args[cur_arg + 1])) {
3809 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3810 file, linenum, args[0], args[1], ptr_arg);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003815 free(curproxy->expect_str);
3816 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3817 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003818 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3819 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3820 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3821 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825 }
3826 else if (strcmp(ptr_arg, "rstring") == 0) {
3827 if (!*(args[cur_arg + 1])) {
3828 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3829 file, linenum, args[0], args[1], ptr_arg);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
3832 }
3833 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003834 free(curproxy->expect_str);
3835 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3836 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003837 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3838 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3839 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3840 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 }
3845 else {
3846 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3847 file, linenum, args[0], args[1], ptr_arg);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003852 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003853 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 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003856 }
3857 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003858 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003859 if (curproxy == &defproxy) {
3860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003863 }
3864
Willy Tarreaub80c2302007-11-30 20:51:32 +01003865 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003867
3868 if (strcmp(args[1], "fail") == 0) {
3869 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003870 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003871 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3872 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 }
3876
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003877 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3878 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3879 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003882 }
3883 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3884 }
3885 else {
3886 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003889 }
3890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891#ifdef TPROXY
3892 else if (!strcmp(args[0], "transparent")) {
3893 /* enable transparent proxy connections */
3894 curproxy->options |= PR_O_TRANSP;
3895 }
3896#endif
3897 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003898 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003899 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003900
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 if (*(args[1]) == 0) {
3902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 }
3906 curproxy->maxconn = atol(args[1]);
3907 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003908 else if (!strcmp(args[0], "backlog")) { /* backlog */
3909 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003911
3912 if (*(args[1]) == 0) {
3913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003914 err_code |= ERR_ALERT | ERR_FATAL;
3915 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003916 }
3917 curproxy->backlog = atol(args[1]);
3918 }
Willy Tarreau86034312006-12-29 00:10:33 +01003919 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003920 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003922
Willy Tarreau86034312006-12-29 00:10:33 +01003923 if (*(args[1]) == 0) {
3924 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003927 }
3928 curproxy->fullconn = atol(args[1]);
3929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3931 if (*(args[1]) == 0) {
3932 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003936 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3937 if (err) {
3938 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3939 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003942 }
3943 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 }
3945 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003946 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003947 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003948 char *err_msg = NULL;
3949 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003950
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 if (curproxy == &defproxy) {
3952 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003955 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003956 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003958
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003959 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003960 if (!sk) {
Willy Tarreauf3559bf2013-03-06 16:52:04 +01003961 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
3962 err_code |= ERR_ALERT | ERR_FATAL;
3963 free(err_msg);
3964 goto out;
3965 }
3966 free(err_msg);
3967
3968 proto = protocol_by_family(sk->ss_family);
3969 if (!proto || !proto->connect) {
3970 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
3971 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975
3976 if (port1 != port2) {
3977 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
3978 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003982
3983 if (!port1) {
3984 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
3985 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01003989
Willy Tarreaud5191e72010-02-09 20:50:45 +01003990 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003991 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
3993 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003994 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003996
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003997 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3998 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004003 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4004 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4005 err_code |= ERR_WARN;
4006
4007 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4008 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4009 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4010 }
4011 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4012 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4013 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4014 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004015 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4016 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4017 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4018 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004019 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004020 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004021 err_code |= ERR_ALERT | ERR_FATAL;
4022 goto out;
4023 }
4024 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 short realport = 0;
4028 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004035 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037
4038 if (!*args[2]) {
4039 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4040 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004044
4045 err = invalid_char(args[1]);
4046 if (err) {
4047 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4048 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004051 }
4052
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004054 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004055 int port1, port2;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004056
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004057 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4058 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4059 err_code |= ERR_ALERT | ERR_ABORT;
4060 goto out;
4061 }
4062
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 /* the servers are linked backwards first */
4064 newsrv->next = curproxy->srv;
4065 curproxy->srv = newsrv;
4066 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004067 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004070 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004071 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004072 LIST_INIT(&newsrv->pendconns);
4073 do_check = 0;
4074 newsrv->state = SRV_RUNNING; /* early server setup */
4075 newsrv->last_change = now.tv_sec;
4076 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004078 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004079 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004080 * - IP: => port=+0, relative
4081 * - IP:N => port=N, absolute
4082 * - IP:+N => port=+N, relative
4083 * - IP:-N => port=-N, relative
4084 */
Willy Tarreaud393a622013-03-04 18:22:00 +01004085 sk = str2sa_range(args[2], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004086 if (!sk) {
4087 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004091
4092 if (!port1 || !port2) {
4093 /* no port specified, +offset, -offset */
4094 newsrv->state |= SRV_MAPPORTS;
4095 }
4096 else if (port1 != port2) {
4097 /* port range */
4098 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4099 file, linenum, args[0], args[1], args[2]);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103 else {
4104 /* used by checks */
4105 realport = port1;
4106 }
4107
Willy Tarreaud5191e72010-02-09 20:50:45 +01004108 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004109 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4110 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004111
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004112 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004113 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4114 file, linenum, newsrv->addr.ss_family, args[2]);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004119 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004120 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 newsrv->inter = curproxy->defsrv.inter;
4122 newsrv->fastinter = curproxy->defsrv.fastinter;
4123 newsrv->downinter = curproxy->defsrv.downinter;
4124 newsrv->rise = curproxy->defsrv.rise;
4125 newsrv->fall = curproxy->defsrv.fall;
4126 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4127 newsrv->minconn = curproxy->defsrv.minconn;
4128 newsrv->maxconn = curproxy->defsrv.maxconn;
4129 newsrv->slowstart = curproxy->defsrv.slowstart;
4130 newsrv->onerror = curproxy->defsrv.onerror;
4131 newsrv->consecutive_errors_limit
4132 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004133#ifdef OPENSSL
4134 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4135#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 newsrv->uweight = newsrv->iweight
4137 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004139 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004141 cur_arg = 3;
4142 } else {
4143 newsrv = &curproxy->defsrv;
4144 cur_arg = 1;
4145 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004146
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004148 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 newsrv->cookie = strdup(args[cur_arg + 1]);
4150 newsrv->cklen = strlen(args[cur_arg + 1]);
4151 cur_arg += 2;
4152 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004154 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4155 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4156 cur_arg += 2;
4157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004159 if (!*args[cur_arg + 1]) {
4160 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4161 file, linenum, args[cur_arg]);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
4165
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004167 if (newsrv->rise <= 0) {
4168 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4169 file, linenum, args[cur_arg]);
4170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
4172 }
4173
Willy Tarreau96839092010-03-29 10:02:24 +02004174 if (newsrv->health)
4175 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 cur_arg += 2;
4177 }
4178 else if (!strcmp(args[cur_arg], "fall")) {
4179 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004180
4181 if (!*args[cur_arg + 1]) {
4182 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4183 file, linenum, args[cur_arg]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187
4188 if (newsrv->fall <= 0) {
4189 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4190 file, linenum, args[cur_arg]);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193 }
4194
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 cur_arg += 2;
4196 }
4197 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004198 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4199 if (err) {
4200 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4201 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004204 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004205 if (val <= 0) {
4206 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4207 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004210 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004211 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 cur_arg += 2;
4213 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004214 else if (!strcmp(args[cur_arg], "fastinter")) {
4215 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4216 if (err) {
4217 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4218 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004221 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004222 if (val <= 0) {
4223 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4224 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004227 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004228 newsrv->fastinter = val;
4229 cur_arg += 2;
4230 }
4231 else if (!strcmp(args[cur_arg], "downinter")) {
4232 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4233 if (err) {
4234 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4235 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004238 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004239 if (val <= 0) {
4240 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4241 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004244 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004245 newsrv->downinter = val;
4246 cur_arg += 2;
4247 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004248 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004249 struct sockaddr_storage *sk;
4250 int port1, port2;
4251
Willy Tarreaud393a622013-03-04 18:22:00 +01004252 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004253 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004254 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4255 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004259 if (port1 != port2) {
4260 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4261 file, linenum, args[cur_arg], args[cur_arg + 1]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004266 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004267 cur_arg += 2;
4268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004269 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004270 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 cur_arg += 2;
4272 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004273 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 newsrv->state |= SRV_BACKUP;
4275 cur_arg ++;
4276 }
Simon Hormanfa461682011-06-25 09:39:49 +09004277 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4278 newsrv->state |= SRV_NON_STICK;
4279 cur_arg ++;
4280 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004281 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4282 newsrv->state |= SRV_SEND_PROXY;
4283 cur_arg ++;
4284 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004285 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4286 newsrv->check.send_proxy = 1;
4287 cur_arg ++;
4288 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 else if (!strcmp(args[cur_arg], "weight")) {
4290 int w;
4291 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004292 if (w < 0 || w > 256) {
4293 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004298 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004299 cur_arg += 2;
4300 }
4301 else if (!strcmp(args[cur_arg], "minconn")) {
4302 newsrv->minconn = atol(args[cur_arg + 1]);
4303 cur_arg += 2;
4304 }
4305 else if (!strcmp(args[cur_arg], "maxconn")) {
4306 newsrv->maxconn = atol(args[cur_arg + 1]);
4307 cur_arg += 2;
4308 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004309 else if (!strcmp(args[cur_arg], "maxqueue")) {
4310 newsrv->maxqueue = atol(args[cur_arg + 1]);
4311 cur_arg += 2;
4312 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004313 else if (!strcmp(args[cur_arg], "slowstart")) {
4314 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004315 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004316 if (err) {
4317 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4318 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004321 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004322 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004323 cur_arg += 2;
4324 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004325 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004326
4327 if (!*args[cur_arg + 1]) {
4328 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4329 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004332 }
4333
4334 newsrv->trackit = strdup(args[cur_arg + 1]);
4335
4336 cur_arg += 2;
4337 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004338 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 global.maxsock++;
4340 do_check = 1;
4341 cur_arg += 1;
4342 }
Willy Tarreau96839092010-03-29 10:02:24 +02004343 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4344 newsrv->state |= SRV_MAINTAIN;
4345 newsrv->state &= ~SRV_RUNNING;
4346 newsrv->health = 0;
4347 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004348 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004349 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004350 if (!strcmp(args[cur_arg + 1], "none"))
4351 newsrv->observe = HANA_OBS_NONE;
4352 else if (!strcmp(args[cur_arg + 1], "layer4"))
4353 newsrv->observe = HANA_OBS_LAYER4;
4354 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4355 if (curproxy->mode != PR_MODE_HTTP) {
4356 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4357 file, linenum, args[cur_arg + 1]);
4358 err_code |= ERR_ALERT;
4359 }
4360 newsrv->observe = HANA_OBS_LAYER7;
4361 }
4362 else {
4363 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004364 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004365 file, linenum, args[cur_arg], args[cur_arg + 1]);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
4369
4370 cur_arg += 2;
4371 }
4372 else if (!strcmp(args[cur_arg], "on-error")) {
4373 if (!strcmp(args[cur_arg + 1], "fastinter"))
4374 newsrv->onerror = HANA_ONERR_FASTINTER;
4375 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4376 newsrv->onerror = HANA_ONERR_FAILCHK;
4377 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4378 newsrv->onerror = HANA_ONERR_SUDDTH;
4379 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4380 newsrv->onerror = HANA_ONERR_MARKDWN;
4381 else {
4382 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004383 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004384 file, linenum, args[cur_arg], args[cur_arg + 1]);
4385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
4387 }
4388
4389 cur_arg += 2;
4390 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004391 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4392 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4393 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4394 else {
4395 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4396 file, linenum, args[cur_arg], args[cur_arg + 1]);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
4400
4401 cur_arg += 2;
4402 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004403 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4404 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4405 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4406 else {
4407 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4408 file, linenum, args[cur_arg], args[cur_arg + 1]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
4412
4413 cur_arg += 2;
4414 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004415 else if (!strcmp(args[cur_arg], "error-limit")) {
4416 if (!*args[cur_arg + 1]) {
4417 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4418 file, linenum, args[cur_arg]);
4419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
4421 }
4422
4423 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4424
4425 if (newsrv->consecutive_errors_limit <= 0) {
4426 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4427 file, linenum, args[cur_arg]);
4428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
4430 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004431 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004432 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004433 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004434 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004435 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004436
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004438 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4439 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004443 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud393a622013-03-04 18:22:00 +01004444 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004445 if (!sk) {
4446 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
4449 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004450 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004451
4452 if (port_low != port_high) {
4453 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004454
4455 if (!port_low || !port_high) {
4456 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4457 file, linenum, args[cur_arg], args[cur_arg + 1]);
4458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
4460 }
4461
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004462 if (port_low <= 0 || port_low > 65535 ||
4463 port_high <= 0 || port_high > 65535 ||
4464 port_low > port_high) {
4465 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4466 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004469 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004470 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4471 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4472 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004473 }
4474
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004476 while (*(args[cur_arg])) {
4477 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004478#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4479#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004480 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004481 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4482 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004485 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004486#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004488 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004489 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 }
4493 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004494 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4495 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004497 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4498 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004499 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4500 char *name, *end;
4501
4502 name = args[cur_arg+1] + 7;
4503 while (isspace(*name))
4504 name++;
4505
4506 end = name;
4507 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4508 end++;
4509
Willy Tarreauef9a3602012-12-08 22:29:20 +01004510 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4511 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4512 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4513 newsrv->conn_src.bind_hdr_len = end - name;
4514 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4515 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4516 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004517
4518 /* now look for an occurrence number */
4519 while (isspace(*end))
4520 end++;
4521 if (*end == ',') {
4522 end++;
4523 name = end;
4524 if (*end == '-')
4525 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004526 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004527 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004528 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004529 }
4530
Willy Tarreauef9a3602012-12-08 22:29:20 +01004531 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004532 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4533 " occurrences values smaller than %d.\n",
4534 file, linenum, MAX_HDR_HISTORY);
4535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004538 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004539 struct sockaddr_storage *sk;
4540 int port1, port2;
4541
Willy Tarreaud393a622013-03-04 18:22:00 +01004542 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004543 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004544 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4545 file, linenum, args[cur_arg], args[cur_arg + 1]);
4546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
4548 }
4549 if (port1 != port2) {
4550 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4551 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004555 newsrv->conn_src.tproxy_addr = *sk;
4556 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004557 }
4558 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004559#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004560 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004561#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004562 cur_arg += 2;
4563 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004564#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004565 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004566 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004569#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4570 } /* "usesrc" */
4571
4572 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4573#ifdef SO_BINDTODEVICE
4574 if (!*args[cur_arg + 1]) {
4575 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004579 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004580 free(newsrv->conn_src.iface_name);
4581 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4582 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004583 global.last_checks |= LSTCHK_NETADM;
4584#else
4585 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4586 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004589#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004590 cur_arg += 2;
4591 continue;
4592 }
4593 /* this keyword in not an option of "source" */
4594 break;
4595 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004597 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004598 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4599 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004604 static int srv_dumped;
4605 struct srv_kw *kw;
4606 char *err;
4607
4608 kw = srv_find_kw(args[cur_arg]);
4609 if (kw) {
4610 char *err = NULL;
4611 int code;
4612
4613 if (!kw->parse) {
4614 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4615 file, linenum, args[0], args[1], args[cur_arg]);
4616 cur_arg += 1 + kw->skip ;
4617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
4619 }
4620
4621 if (defsrv && !kw->default_ok) {
4622 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4623 file, linenum, args[0], args[1], args[cur_arg]);
4624 cur_arg += 1 + kw->skip ;
4625 err_code |= ERR_ALERT;
4626 continue;
4627 }
4628
4629 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4630 err_code |= code;
4631
4632 if (code) {
4633 if (err && *err) {
4634 indent_msg(&err, 2);
4635 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4636 }
4637 else
4638 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4639 file, linenum, args[0], args[1], args[cur_arg]);
4640 if (code & ERR_FATAL) {
4641 free(err);
4642 cur_arg += 1 + kw->skip;
4643 goto out;
4644 }
4645 }
4646 free(err);
4647 cur_arg += 1 + kw->skip;
4648 continue;
4649 }
4650
4651 err = NULL;
4652 if (!srv_dumped) {
4653 srv_dump_kws(&err);
4654 indent_msg(&err, 4);
4655 srv_dumped = 1;
4656 }
4657
4658 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4659 file, linenum, args[0], args[1], args[cur_arg],
4660 err ? " Registered keywords :" : "", err ? err : "");
4661 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004662
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 }
4666 }
4667
4668 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004669 if (newsrv->trackit) {
4670 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4671 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004674 }
4675
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004676 /* If neither a port nor an addr was specified and no check transport
4677 * layer is forced, then the transport layer used by the checks is the
4678 * same as for the production traffic. Otherwise we use raw_sock by
4679 * default, unless one is specified.
4680 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004681 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004682#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004683 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004684#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004685 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4686 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004687 /* try to get the port from check.addr if check.port not set */
4688 if (!newsrv->check.port)
4689 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004690
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004691 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004692 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004693
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004694 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004695 /* not yet valid, because no port was set on
4696 * the server either. We'll check if we have
4697 * a known port on the first listener.
4698 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004699 struct listener *l;
4700
4701 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004702 newsrv->check.port = get_host_port(&l->addr);
4703 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004704 break;
4705 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004706 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004707 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004708 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4709 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004713
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004714 /* Allocate buffer for check requests... */
4715 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004716 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4717 err_code |= ERR_ALERT | ERR_ABORT;
4718 goto out;
4719 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004720 newsrv->check.bi->size = global.tune.chksize;
4721
4722 /* Allocate buffer for check responses... */
4723 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4724 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4725 err_code |= ERR_ALERT | ERR_ABORT;
4726 goto out;
4727 }
4728 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004729
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004730 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004731 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004732 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4733 err_code |= ERR_ALERT | ERR_ABORT;
4734 goto out;
4735 }
4736
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004737 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4738 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 newsrv->state |= SRV_CHECKED;
4740 }
4741
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004742 if (!defsrv) {
4743 if (newsrv->state & SRV_BACKUP)
4744 curproxy->srv_bck++;
4745 else
4746 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004747
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004748 newsrv->prev_state = newsrv->state;
4749 }
William Lallemanda73203e2012-03-12 12:48:57 +01004750 }
4751
4752 else if (strcmp(args[0], "unique-id-format") == 0) {
4753 if (!*(args[1])) {
4754 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
4757 }
William Lallemand3203ff42012-11-11 17:30:56 +01004758 if (*(args[2])) {
4759 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
4762 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004763 free(curproxy->uniqueid_format_string);
4764 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004765 }
William Lallemanda73203e2012-03-12 12:48:57 +01004766
4767 else if (strcmp(args[0], "unique-id-header") == 0) {
4768 if (!*(args[1])) {
4769 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
4773 free(curproxy->header_unique_id);
4774 curproxy->header_unique_id = strdup(args[1]);
4775 }
4776
William Lallemand723b73a2012-02-08 16:37:49 +01004777 else if (strcmp(args[0], "log-format") == 0) {
4778 if (!*(args[1])) {
4779 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
4782 }
William Lallemand3203ff42012-11-11 17:30:56 +01004783 if (*(args[2])) {
4784 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
4787 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004788
4789 if (curproxy->logformat_string != default_http_log_format &&
4790 curproxy->logformat_string != default_tcp_log_format &&
4791 curproxy->logformat_string != clf_http_log_format)
4792 free(curproxy->logformat_string);
4793 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
William Lallemand723b73a2012-02-08 16:37:49 +01004795
William Lallemand0f99e342011-10-12 17:50:54 +02004796 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4797 /* delete previous herited or defined syslog servers */
4798 struct logsrv *back;
4799
4800 if (*(args[1]) != 0) {
4801 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
4804 }
4805
William Lallemand723b73a2012-02-08 16:37:49 +01004806 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4807 LIST_DEL(&tmplogsrv->list);
4808 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004809 }
4810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004812 struct logsrv *logsrv;
4813
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004815 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004816 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004817 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004818 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004819 LIST_INIT(&node->list);
4820 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
4823 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004824 struct sockaddr_storage *sk;
4825 int port1, port2;
4826 char *err_msg = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02004827
4828 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829
William Lallemand0f99e342011-10-12 17:50:54 +02004830 logsrv->facility = get_log_facility(args[2]);
4831 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
4835
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
4837
William Lallemand0f99e342011-10-12 17:50:54 +02004838 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004840 logsrv->level = get_log_level(args[3]);
4841 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
4847 }
4848
William Lallemand0f99e342011-10-12 17:50:54 +02004849 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004850 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004851 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004852 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004853 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
4856
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004857 }
4858 }
4859
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004860 sk = str2sa_range(args[1], &port1, &port2, &err_msg, NULL);
4861 if (!sk) {
4862 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], err_msg);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 free(err_msg);
4865 goto out;
4866 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004867
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004868 logsrv->addr = *sk;
4869 free(err_msg);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004870
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004871 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004872 if (port1 != port2) {
4873 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4874 file, linenum, args[0], args[1]);
4875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
4877 }
4878
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004879 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004880 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 }
William Lallemand0f99e342011-10-12 17:50:54 +02004882
4883 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
4885 else {
4886 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4887 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 }
4891 }
4892 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004894 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004895 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004896
Willy Tarreau977b8e42006-12-29 14:19:17 +01004897 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004899
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004901 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4902 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004903 err_code |= ERR_ALERT | ERR_FATAL;
4904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004906
4907 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004908 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4909 free(curproxy->conn_src.iface_name);
4910 curproxy->conn_src.iface_name = NULL;
4911 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004912
Willy Tarreaud393a622013-03-04 18:22:00 +01004913 sk = str2sa_range(args[1], &port1, &port2, NULL, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004914 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004915 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
4916 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004920
4921 if (port1 != port2) {
4922 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4923 file, linenum, args[0], args[1]);
4924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
4926 }
4927
Willy Tarreauef9a3602012-12-08 22:29:20 +01004928 curproxy->conn_src.source_addr = *sk;
4929 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004930
4931 cur_arg = 2;
4932 while (*(args[cur_arg])) {
4933 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004934#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4935#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004936 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004937 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4938 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941 }
4942#endif
4943 if (!*args[cur_arg + 1]) {
4944 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4945 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948 }
4949
4950 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004951 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4952 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004954 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4955 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004956 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4957 char *name, *end;
4958
4959 name = args[cur_arg+1] + 7;
4960 while (isspace(*name))
4961 name++;
4962
4963 end = name;
4964 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4965 end++;
4966
Willy Tarreauef9a3602012-12-08 22:29:20 +01004967 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4968 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
4969 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4970 curproxy->conn_src.bind_hdr_len = end - name;
4971 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
4972 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
4973 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004974
4975 /* now look for an occurrence number */
4976 while (isspace(*end))
4977 end++;
4978 if (*end == ',') {
4979 end++;
4980 name = end;
4981 if (*end == '-')
4982 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004983 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004984 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004985 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004986 }
4987
Willy Tarreauef9a3602012-12-08 22:29:20 +01004988 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004989 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4990 " occurrences values smaller than %d.\n",
4991 file, linenum, MAX_HDR_HISTORY);
4992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
4994 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004995 } else {
Willy Tarreaud393a622013-03-04 18:22:00 +01004996 struct sockaddr_storage *sk = str2sa_range(args[cur_arg + 1], &port1, &port2, NULL, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997
Willy Tarreaud5191e72010-02-09 20:50:45 +01004998 if (!sk) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004999 Alert("parsing [%s:%d] : '%s' : unknown host in '%s'\n",
5000 file, linenum, args[cur_arg], args[cur_arg + 1]);
5001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
5003 }
5004 if (port1 != port2) {
5005 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5006 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005010 curproxy->conn_src.tproxy_addr = *sk;
5011 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005012 }
5013 global.last_checks |= LSTCHK_NETADM;
5014#if !defined(CONFIG_HAP_LINUX_TPROXY)
5015 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005016#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017#else /* no TPROXY support */
5018 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005019 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005022#endif
5023 cur_arg += 2;
5024 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005025 }
5026
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005027 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5028#ifdef SO_BINDTODEVICE
5029 if (!*args[cur_arg + 1]) {
5030 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005034 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005035 free(curproxy->conn_src.iface_name);
5036 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5037 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005038 global.last_checks |= LSTCHK_NETADM;
5039#else
5040 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5041 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005044#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045 cur_arg += 2;
5046 continue;
5047 }
5048 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005049 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005054 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5055 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5056 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5063 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005067
5068 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005069 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005070 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 }
5074 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005076 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005077 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
5081 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005083 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005084 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
5088 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005089 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005090 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005091 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
5095 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005097 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005098 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005102 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005104 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005105 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005107 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005108 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005109 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005111 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005112 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005114 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005115 }
5116 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005118 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005119 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005121 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5126 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005130
5131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005133 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005139 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005140 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
5144 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005147 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
5158 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005161 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005165 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005167 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005168 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005170 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005173 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005174
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 if (curproxy == &defproxy) {
5176 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005180 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005181 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 if (*(args[1]) == 0) {
5184 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005188
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005189 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005190 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5191 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5192 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
5195 }
5196 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5197 }
5198 else if (*args[2]) {
5199 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5200 file, linenum, args[0], args[2]);
5201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
5203 }
5204
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005205 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005206 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005207 wl->s = strdup(args[1]);
5208 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005209 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005212 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005218
Willy Tarreauade5ec42010-01-28 19:33:49 +01005219 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005220 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005221 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005223 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
5225 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005227 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005228 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005229 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
5232 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005234 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005235 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005236 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 }
5239 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005240 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245 }
5246
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005248 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005249 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
5253 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005255 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
5260 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005262 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005263 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005268 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005269
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 if (curproxy == &defproxy) {
5271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005275 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 if (*(args[1]) == 0) {
5279 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005284 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005285 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5286 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5287 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005288 err_code |= ERR_ALERT | ERR_FATAL;
5289 goto out;
5290 }
5291 err_code |= warnif_cond_requires_req(cond, file, linenum);
5292 }
5293 else if (*args[2]) {
5294 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5295 file, linenum, args[0], args[2]);
5296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298 }
5299
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005300 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005301 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005302 wl->s = strdup(args[1]);
5303 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
5305 else if (!strcmp(args[0], "errorloc") ||
5306 !strcmp(args[0], "errorloc302") ||
5307 !strcmp(args[0], "errorloc303")) { /* error location */
5308 int errnum, errlen;
5309 char *err;
5310
Willy Tarreau977b8e42006-12-29 14:19:17 +01005311 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005312 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005315 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 }
5319
5320 errnum = atol(args[1]);
5321 if (!strcmp(args[0], "errorloc303")) {
5322 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5323 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5324 } else {
5325 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5326 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5327 }
5328
Willy Tarreau0f772532006-12-23 20:51:41 +01005329 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5330 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005331 chunk_destroy(&curproxy->errmsg[rc]);
5332 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005333 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005336
5337 if (rc >= HTTP_ERR_SIZE) {
5338 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5339 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 free(err);
5341 }
5342 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005343 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5344 int errnum, errlen, fd;
5345 char *err;
5346 struct stat stat;
5347
5348 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005349 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005350
5351 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005352 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005355 }
5356
5357 fd = open(args[2], O_RDONLY);
5358 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5359 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5360 file, linenum, args[2], args[1]);
5361 if (fd >= 0)
5362 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005365 }
5366
Willy Tarreau27a674e2009-08-17 07:23:33 +02005367 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005368 errlen = stat.st_size;
5369 } else {
5370 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005371 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005373 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005374 }
5375
5376 err = malloc(errlen); /* malloc() must succeed during parsing */
5377 errnum = read(fd, err, errlen);
5378 if (errnum != errlen) {
5379 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5380 file, linenum, args[2], args[1]);
5381 close(fd);
5382 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005385 }
5386 close(fd);
5387
5388 errnum = atol(args[1]);
5389 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5390 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005391 chunk_destroy(&curproxy->errmsg[rc]);
5392 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005393 break;
5394 }
5395 }
5396
5397 if (rc >= HTTP_ERR_SIZE) {
5398 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5399 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005400 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005401 free(err);
5402 }
5403 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005404 else if (!strcmp(args[0], "compression")) {
5405 struct comp *comp;
5406 if (curproxy->comp == NULL) {
5407 comp = calloc(1, sizeof(struct comp));
5408 curproxy->comp = comp;
5409 } else {
5410 comp = curproxy->comp;
5411 }
5412
5413 if (!strcmp(args[1], "algo")) {
5414 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005415 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005416
William Lallemand82fe75c2012-10-23 10:25:10 +02005417 cur_arg = 2;
5418 if (!*args[cur_arg]) {
5419 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5420 file, linenum, args[0]);
5421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424 while (*(args[cur_arg])) {
5425 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5426 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5427 file, linenum, args[0], args[cur_arg]);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
William Lallemand552df672012-11-07 13:21:47 +01005431 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5432 curproxy->comp->algos->end(&ctx);
5433 } else {
5434 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5435 file, linenum, args[0], args[cur_arg]);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005439 cur_arg ++;
5440 continue;
5441 }
5442 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005443 else if (!strcmp(args[1], "offload")) {
5444 comp->offload = 1;
5445 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005446 else if (!strcmp(args[1], "type")) {
5447 int cur_arg;
5448 cur_arg = 2;
5449 if (!*args[cur_arg]) {
5450 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5451 file, linenum, args[0]);
5452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
5454 }
5455 while (*(args[cur_arg])) {
5456 comp_append_type(comp, args[cur_arg]);
5457 cur_arg ++;
5458 continue;
5459 }
5460 }
5461 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005462 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005463 file, linenum, args[0]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005469 struct cfg_kw_list *kwl;
5470 int index;
5471
5472 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5473 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5474 if (kwl->kw[index].section != CFG_LISTEN)
5475 continue;
5476 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5477 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005478 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005479 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005480 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005483 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005484 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005485 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005486 err_code |= ERR_WARN;
5487 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005488 }
Willy Tarreau93893792009-07-23 13:19:11 +02005489 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005490 }
5491 }
5492 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005493
Willy Tarreau6daf3432008-01-22 16:44:08 +01005494 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 }
Willy Tarreau93893792009-07-23 13:19:11 +02005498 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005499 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005500 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501}
5502
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005503int
5504cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5505{
5506
5507 int err_code = 0;
5508 const char *err;
5509
5510 if (!strcmp(args[0], "userlist")) { /* new userlist */
5511 struct userlist *newul;
5512
5513 if (!*args[1]) {
5514 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5515 file, linenum, args[0]);
5516 err_code |= ERR_ALERT | ERR_FATAL;
5517 goto out;
5518 }
5519
5520 err = invalid_char(args[1]);
5521 if (err) {
5522 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5523 file, linenum, *err, args[0], args[1]);
5524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526 }
5527
5528 for (newul = userlist; newul; newul = newul->next)
5529 if (!strcmp(newul->name, args[1])) {
5530 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5531 file, linenum, args[1]);
5532 err_code |= ERR_WARN;
5533 goto out;
5534 }
5535
5536 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5537 if (!newul) {
5538 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5539 err_code |= ERR_ALERT | ERR_ABORT;
5540 goto out;
5541 }
5542
5543 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5544 newul->name = strdup(args[1]);
5545
5546 if (!newul->groupusers | !newul->name) {
5547 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5548 err_code |= ERR_ALERT | ERR_ABORT;
5549 goto out;
5550 }
5551
5552 newul->next = userlist;
5553 userlist = newul;
5554
5555 } else if (!strcmp(args[0], "group")) { /* new group */
5556 int cur_arg, i;
5557 const char *err;
5558
5559 if (!*args[1]) {
5560 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5561 file, linenum, args[0]);
5562 err_code |= ERR_ALERT | ERR_FATAL;
5563 goto out;
5564 }
5565
5566 err = invalid_char(args[1]);
5567 if (err) {
5568 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5569 file, linenum, *err, args[0], args[1]);
5570 err_code |= ERR_ALERT | ERR_FATAL;
5571 goto out;
5572 }
5573
5574 for(i = 0; i < userlist->grpcnt; i++)
5575 if (!strcmp(userlist->groups[i], args[1])) {
5576 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5577 file, linenum, args[1], userlist->name);
5578 err_code |= ERR_ALERT;
5579 goto out;
5580 }
5581
5582 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5583 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5584 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
5587 }
5588
5589 cur_arg = 2;
5590
5591 while (*args[cur_arg]) {
5592 if (!strcmp(args[cur_arg], "users")) {
5593 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5594 cur_arg += 2;
5595 continue;
5596 } else {
5597 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5598 file, linenum, args[0]);
5599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
5601 }
5602 }
5603
5604 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5605 } else if (!strcmp(args[0], "user")) { /* new user */
5606 struct auth_users *newuser;
5607 int cur_arg;
5608
5609 if (!*args[1]) {
5610 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5611 file, linenum, args[0]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
5616 for (newuser = userlist->users; newuser; newuser = newuser->next)
5617 if (!strcmp(newuser->user, args[1])) {
5618 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5619 file, linenum, args[1], userlist->name);
5620 err_code |= ERR_ALERT;
5621 goto out;
5622 }
5623
5624 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5625 if (!newuser) {
5626 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5627 err_code |= ERR_ALERT | ERR_ABORT;
5628 goto out;
5629 }
5630
5631 newuser->user = strdup(args[1]);
5632
5633 newuser->next = userlist->users;
5634 userlist->users = newuser;
5635
5636 cur_arg = 2;
5637
5638 while (*args[cur_arg]) {
5639 if (!strcmp(args[cur_arg], "password")) {
5640#ifndef CONFIG_HAP_CRYPT
5641 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5642 file, linenum);
5643 err_code |= ERR_ALERT;
5644#endif
5645 newuser->pass = strdup(args[cur_arg + 1]);
5646 cur_arg += 2;
5647 continue;
5648 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5649 newuser->pass = strdup(args[cur_arg + 1]);
5650 newuser->flags |= AU_O_INSECURE;
5651 cur_arg += 2;
5652 continue;
5653 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005654 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005655 cur_arg += 2;
5656 continue;
5657 } else {
5658 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5659 file, linenum, args[0]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663 }
5664 } else {
5665 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5666 err_code |= ERR_ALERT | ERR_FATAL;
5667 }
5668
5669out:
5670 return err_code;
5671}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005672
5673/*
5674 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005675 * Returns the error code, 0 if OK, or any combination of :
5676 * - ERR_ABORT: must abort ASAP
5677 * - ERR_FATAL: we can continue parsing but not start the service
5678 * - ERR_WARN: a warning has been emitted
5679 * - ERR_ALERT: an alert has been emitted
5680 * Only the two first ones can stop processing, the two others are just
5681 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005683int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005685 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 FILE *f;
5687 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005689 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005690
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 if ((f=fopen(file,"r")) == NULL)
5692 return -1;
5693
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005694 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005695 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005696 char *end;
5697 char *args[MAX_LINE_ARGS + 1];
5698 char *line = thisline;
5699
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 linenum++;
5701
5702 end = line + strlen(line);
5703
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005704 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5705 /* Check if we reached the limit and the last char is not \n.
5706 * Watch out for the last line without the terminating '\n'!
5707 */
5708 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005709 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005711 }
5712
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005714 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 line++;
5716
5717 arg = 0;
5718 args[arg] = line;
5719
5720 while (*line && arg < MAX_LINE_ARGS) {
5721 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5722 * C equivalent value. Other combinations left unchanged (eg: \1).
5723 */
5724 if (*line == '\\') {
5725 int skip = 0;
5726 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5727 *line = line[1];
5728 skip = 1;
5729 }
5730 else if (line[1] == 'r') {
5731 *line = '\r';
5732 skip = 1;
5733 }
5734 else if (line[1] == 'n') {
5735 *line = '\n';
5736 skip = 1;
5737 }
5738 else if (line[1] == 't') {
5739 *line = '\t';
5740 skip = 1;
5741 }
5742 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005743 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 unsigned char hex1, hex2;
5745 hex1 = toupper(line[2]) - '0';
5746 hex2 = toupper(line[3]) - '0';
5747 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5748 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5749 *line = (hex1<<4) + hex2;
5750 skip = 3;
5751 }
5752 else {
5753 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
5756 }
5757 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005758 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 end -= skip;
5760 }
5761 line++;
5762 }
5763 else if (*line == '#' || *line == '\n' || *line == '\r') {
5764 /* end of string, end of loop */
5765 *line = 0;
5766 break;
5767 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005768 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005770 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005771 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 line++;
5773 args[++arg] = line;
5774 }
5775 else {
5776 line++;
5777 }
5778 }
5779
5780 /* empty line */
5781 if (!**args)
5782 continue;
5783
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005784 if (*line) {
5785 /* we had to stop due to too many args.
5786 * Let's terminate the string, print the offending part then cut the
5787 * last arg.
5788 */
5789 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5790 line++;
5791 *line = '\0';
5792
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005793 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005794 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005795 err_code |= ERR_ALERT | ERR_FATAL;
5796 args[arg] = line;
5797 }
5798
Willy Tarreau540abe42007-05-02 20:50:16 +02005799 /* zero out remaining args and ensure that at least one entry
5800 * is zeroed out.
5801 */
5802 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 args[arg] = line;
5804 }
5805
Willy Tarreau3842f002009-06-14 11:39:52 +02005806 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005807 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005808 char *tmp;
5809
Willy Tarreau3842f002009-06-14 11:39:52 +02005810 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005811 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005812 for (arg=0; *args[arg+1]; arg++)
5813 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005814 *tmp = '\0'; // fix the next arg to \0
5815 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005816 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005817 else if (!strcmp(args[0], "default")) {
5818 kwm = KWM_DEF;
5819 for (arg=0; *args[arg+1]; arg++)
5820 args[arg] = args[arg+1]; // shift args after inversion
5821 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005822
William Lallemand0f99e342011-10-12 17:50:54 +02005823 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5824 strcmp(args[0], "log") != 0) {
5825 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005826 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005827 }
5828
Willy Tarreau977b8e42006-12-29 14:19:17 +01005829 if (!strcmp(args[0], "listen") ||
5830 !strcmp(args[0], "frontend") ||
5831 !strcmp(args[0], "backend") ||
5832 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005833 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005835 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005836 cursection = strdup(args[0]);
5837 }
5838 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005840 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005841 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005842 }
5843 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005844 confsect = CFG_USERLIST;
5845 free(cursection);
5846 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005847 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005848 else if (!strcmp(args[0], "peers")) {
5849 confsect = CFG_PEERS;
5850 free(cursection);
5851 cursection = strdup(args[0]);
5852 }
5853
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 /* else it's a section keyword */
5855
5856 switch (confsect) {
5857 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005858 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 break;
5860 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005861 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005863 case CFG_USERLIST:
5864 err_code |= cfg_parse_users(file, linenum, args, kwm);
5865 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005866 case CFG_PEERS:
5867 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5868 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005870 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005871 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005873
5874 if (err_code & ERR_ABORT)
5875 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005877 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005878 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005880 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005881}
5882
Willy Tarreaubb925012009-07-23 13:36:36 +02005883/*
5884 * Returns the error code, 0 if OK, or any combination of :
5885 * - ERR_ABORT: must abort ASAP
5886 * - ERR_FATAL: we can continue parsing but not start the service
5887 * - ERR_WARN: a warning has been emitted
5888 * - ERR_ALERT: an alert has been emitted
5889 * Only the two first ones can stop processing, the two others are just
5890 * indicators.
5891 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005892int check_config_validity()
5893{
5894 int cfgerr = 0;
5895 struct proxy *curproxy = NULL;
5896 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005897 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005898 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005899 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005900 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005902 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005903 /*
5904 * Now, check for the integrity of all that we have collected.
5905 */
5906
5907 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005908 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909
Willy Tarreau193b8c62012-11-22 00:17:38 +01005910 if (!global.tune.max_http_hdr)
5911 global.tune.max_http_hdr = MAX_HTTP_HDR;
5912
5913 if (!global.tune.cookie_len)
5914 global.tune.cookie_len = CAPTURE_LEN;
5915
5916 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
5917
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005918 /* first, we will invert the proxy list order */
5919 curproxy = NULL;
5920 while (proxy) {
5921 struct proxy *next;
5922
5923 next = proxy->next;
5924 proxy->next = curproxy;
5925 curproxy = proxy;
5926 if (!next)
5927 break;
5928 proxy = next;
5929 }
5930
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005932 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005933 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005934 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005935 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005936 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005937 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005938 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005939
Willy Tarreau050536d2012-10-04 08:47:34 +02005940 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005941 /* proxy ID not set, use automatic numbering with first
5942 * spare entry starting with next_pxid.
5943 */
5944 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5945 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5946 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005947 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005948 next_pxid++;
5949
Willy Tarreau55ea7572007-06-17 19:56:27 +02005950
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005952 /* ensure we don't keep listeners uselessly bound */
5953 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 curproxy = curproxy->next;
5955 continue;
5956 }
5957
Willy Tarreau16a21472012-11-19 12:39:59 +01005958 /* number of processes this proxy is bound to */
5959 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5960
Willy Tarreauff01a212009-03-15 13:46:16 +01005961 switch (curproxy->mode) {
5962 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005963 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005964 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005965 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5966 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005967 cfgerr++;
5968 }
5969
5970 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005971 Warning("config : servers will be ignored for %s '%s'.\n",
5972 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005973 break;
5974
5975 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005976 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005977 break;
5978
5979 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005980 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005981 break;
5982 }
5983
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005984 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005985 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005986 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005987 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5988 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005989 cfgerr++;
5990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005992 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005993 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5994 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005995 cfgerr++;
5996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005998 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005999 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6000 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006001 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006002 }
6003 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006004 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006005 /* If no LB algo is set in a backend, and we're not in
6006 * transparent mode, dispatch mode nor proxy mode, we
6007 * want to use balance roundrobin by default.
6008 */
6009 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6010 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006011 }
6012 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006013
Willy Tarreau1620ec32011-08-06 17:05:02 +02006014 if (curproxy->options & PR_O_DISPATCH)
6015 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6016 else if (curproxy->options & PR_O_HTTP_PROXY)
6017 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6018 else if (curproxy->options & PR_O_TRANSP)
6019 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006020
Willy Tarreau1620ec32011-08-06 17:05:02 +02006021 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6022 if (curproxy->options & PR_O_DISABLE404) {
6023 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6024 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6025 err_code |= ERR_WARN;
6026 curproxy->options &= ~PR_O_DISABLE404;
6027 }
6028 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6029 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6030 "send-state", proxy_type_str(curproxy), curproxy->id);
6031 err_code |= ERR_WARN;
6032 curproxy->options &= ~PR_O2_CHK_SNDST;
6033 }
Willy Tarreauef781042010-01-27 11:53:01 +01006034 }
6035
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006036 /* if a default backend was specified, let's find it */
6037 if (curproxy->defbe.name) {
6038 struct proxy *target;
6039
Alex Williams96532db2009-11-01 21:27:13 -05006040 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006041 if (!target) {
6042 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6043 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006044 cfgerr++;
6045 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006046 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6047 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006048 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006049 } else {
6050 free(curproxy->defbe.name);
6051 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006052 /* we force the backend to be present on at least all of
6053 * the frontend's processes.
6054 */
6055 target->bind_proc = curproxy->bind_proc ?
6056 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006057
6058 /* Emit a warning if this proxy also has some servers */
6059 if (curproxy->srv) {
6060 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6061 curproxy->id);
6062 err_code |= ERR_WARN;
6063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006064 }
6065 }
6066
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006067 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006068 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6069 /* map jump target for ACT_SETBE in req_rep chain */
6070 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006071 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006072 struct proxy *target;
6073
Willy Tarreaua496b602006-12-17 23:15:24 +01006074 if (exp->action != ACT_SETBE)
6075 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006076
Alex Williams96532db2009-11-01 21:27:13 -05006077 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006078 if (!target) {
6079 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6080 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006081 cfgerr++;
6082 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006083 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6084 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006085 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006086 } else {
6087 free((void *)exp->replace);
6088 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006089 /* we force the backend to be present on at least all of
6090 * the frontend's processes.
6091 */
6092 target->bind_proc = curproxy->bind_proc ?
6093 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006094 }
6095 }
6096 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006097
6098 /* find the target proxy for 'use_backend' rules */
6099 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006100 struct proxy *target;
6101
Alex Williams96532db2009-11-01 21:27:13 -05006102 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006103
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006104 if (!target) {
6105 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6106 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006107 cfgerr++;
6108 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006109 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6110 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006111 cfgerr++;
6112 } else {
6113 free((void *)rule->be.name);
6114 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006115 /* we force the backend to be present on at least all of
6116 * the frontend's processes.
6117 */
6118 target->bind_proc = curproxy->bind_proc ?
6119 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006120 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006121 }
6122
6123 /* find the target proxy for 'use_backend' rules */
6124 list_for_each_entry(srule, &curproxy->server_rules, list) {
6125 struct server *target = findserver(curproxy, srule->srv.name);
6126
6127 if (!target) {
6128 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6129 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6130 cfgerr++;
6131 continue;
6132 }
6133 free((void *)srule->srv.name);
6134 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006135 }
6136
Emeric Brunb982a3d2010-01-04 15:45:53 +01006137 /* find the target table for 'stick' rules */
6138 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6139 struct proxy *target;
6140
Emeric Brun1d33b292010-01-04 15:47:17 +01006141 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6142 if (mrule->flags & STK_IS_STORE)
6143 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6144
Emeric Brunb982a3d2010-01-04 15:45:53 +01006145 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006146 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006147 else
6148 target = curproxy;
6149
6150 if (!target) {
6151 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6152 curproxy->id, mrule->table.name);
6153 cfgerr++;
6154 }
6155 else if (target->table.size == 0) {
6156 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6157 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6158 cfgerr++;
6159 }
Willy Tarreau12785782012-04-27 21:37:17 +02006160 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6161 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006162 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6163 cfgerr++;
6164 }
6165 else {
6166 free((void *)mrule->table.name);
6167 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006168 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006169 }
6170 }
6171
6172 /* find the target table for 'store response' rules */
6173 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6174 struct proxy *target;
6175
Emeric Brun1d33b292010-01-04 15:47:17 +01006176 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6177
Emeric Brunb982a3d2010-01-04 15:45:53 +01006178 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006179 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006180 else
6181 target = curproxy;
6182
6183 if (!target) {
6184 Alert("Proxy '%s': unable to find store table '%s'.\n",
6185 curproxy->id, mrule->table.name);
6186 cfgerr++;
6187 }
6188 else if (target->table.size == 0) {
6189 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6190 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6191 cfgerr++;
6192 }
Willy Tarreau12785782012-04-27 21:37:17 +02006193 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6194 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006195 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6196 cfgerr++;
6197 }
6198 else {
6199 free((void *)mrule->table.name);
6200 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006201 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006202 }
6203 }
6204
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006205 /* find the target table for 'tcp-request' layer 4 rules */
6206 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6207 struct proxy *target;
6208
Willy Tarreau56123282010-08-06 19:06:56 +02006209 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006210 continue;
6211
6212 if (trule->act_prm.trk_ctr.table.n)
6213 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6214 else
6215 target = curproxy;
6216
6217 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006218 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6219 curproxy->id, trule->act_prm.trk_ctr.table.n,
6220 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006221 cfgerr++;
6222 }
6223 else if (target->table.size == 0) {
6224 Alert("Proxy '%s': table '%s' used but not configured.\n",
6225 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6226 cfgerr++;
6227 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006228 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6229 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6230 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6231 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6232 cfgerr++;
6233 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006234 else {
6235 free(trule->act_prm.trk_ctr.table.n);
6236 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006237 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006238 * to pass a list of counters to track and allocate them right here using
6239 * stktable_alloc_data_type().
6240 */
6241 }
6242 }
6243
Willy Tarreaud1f96522010-08-03 19:34:32 +02006244 /* find the target table for 'tcp-request' layer 6 rules */
6245 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6246 struct proxy *target;
6247
Willy Tarreau56123282010-08-06 19:06:56 +02006248 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006249 continue;
6250
6251 if (trule->act_prm.trk_ctr.table.n)
6252 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6253 else
6254 target = curproxy;
6255
6256 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006257 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6258 curproxy->id, trule->act_prm.trk_ctr.table.n,
6259 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006260 cfgerr++;
6261 }
6262 else if (target->table.size == 0) {
6263 Alert("Proxy '%s': table '%s' used but not configured.\n",
6264 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6265 cfgerr++;
6266 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006267 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6268 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6269 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
6270 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
6271 cfgerr++;
6272 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006273 else {
6274 free(trule->act_prm.trk_ctr.table.n);
6275 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006276 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006277 * to pass a list of counters to track and allocate them right here using
6278 * stktable_alloc_data_type().
6279 */
6280 }
6281 }
6282
Emeric Brun32da3c42010-09-23 18:39:19 +02006283 if (curproxy->table.peers.name) {
6284 struct peers *curpeers = peers;
6285
6286 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6287 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6288 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006289 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006290 break;
6291 }
6292 }
6293
6294 if (!curpeers) {
6295 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6296 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006297 free((void *)curproxy->table.peers.name);
6298 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006299 cfgerr++;
6300 }
6301 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006302 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6303 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006304 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006305 cfgerr++;
6306 }
6307 }
6308
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006309 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006310 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006311 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6312 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6313 "proxy", curproxy->id);
6314 cfgerr++;
6315 goto out_uri_auth_compat;
6316 }
6317
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006318 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006319 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006320 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006321 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006322
Willy Tarreau95fa4692010-02-01 13:05:50 +01006323 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6324 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006325
6326 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006327 uri_auth_compat_req[i++] = "realm";
6328 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6329 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006330
Willy Tarreau95fa4692010-02-01 13:05:50 +01006331 uri_auth_compat_req[i++] = "unless";
6332 uri_auth_compat_req[i++] = "{";
6333 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6334 uri_auth_compat_req[i++] = "}";
6335 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006336
Willy Tarreauff011f22011-01-06 17:51:27 +01006337 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6338 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006339 cfgerr++;
6340 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006341 }
6342
Willy Tarreauff011f22011-01-06 17:51:27 +01006343 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006344
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006345 if (curproxy->uri_auth->auth_realm) {
6346 free(curproxy->uri_auth->auth_realm);
6347 curproxy->uri_auth->auth_realm = NULL;
6348 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006349
6350 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006351 }
6352out_uri_auth_compat:
6353
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006354 cfgerr += acl_find_targets(curproxy);
6355
Willy Tarreau2738a142006-07-08 17:28:09 +02006356 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006357 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006358 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006359 (!curproxy->timeout.connect ||
6360 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006361 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006362 " | While not properly invalid, you will certainly encounter various problems\n"
6363 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006364 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006365 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006366 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006367 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006368
Willy Tarreau1fa31262007-12-03 00:36:16 +01006369 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6370 * We must still support older configurations, so let's find out whether those
6371 * parameters have been set or must be copied from contimeouts.
6372 */
6373 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006374 if (!curproxy->timeout.tarpit ||
6375 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006376 /* tarpit timeout not set. We search in the following order:
6377 * default.tarpit, curr.connect, default.connect.
6378 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006379 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006380 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006381 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006382 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006383 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006384 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006385 }
6386 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006387 (!curproxy->timeout.queue ||
6388 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006389 /* queue timeout not set. We search in the following order:
6390 * default.queue, curr.connect, default.connect.
6391 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006392 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006393 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006394 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006395 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006396 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006397 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006398 }
6399 }
6400
Willy Tarreau1620ec32011-08-06 17:05:02 +02006401 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006402 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6403 curproxy->check_req = (char *)malloc(curproxy->check_len);
6404 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006405 }
6406
Willy Tarreau193b8c62012-11-22 00:17:38 +01006407 /* ensure that cookie capture length is not too large */
6408 if (curproxy->capture_len >= global.tune.cookie_len) {
6409 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6410 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6411 err_code |= ERR_WARN;
6412 curproxy->capture_len = global.tune.cookie_len - 1;
6413 }
6414
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006415 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006416 if (curproxy->nb_req_cap) {
6417 if (curproxy->mode == PR_MODE_HTTP) {
6418 curproxy->req_cap_pool = create_pool("ptrcap",
6419 curproxy->nb_req_cap * sizeof(char *),
6420 MEM_F_SHARED);
6421 } else {
6422 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6423 proxy_type_str(curproxy), curproxy->id);
6424 err_code |= ERR_WARN;
6425 curproxy->to_log &= ~LW_REQHDR;
6426 curproxy->nb_req_cap = 0;
6427 }
6428 }
6429
6430 if (curproxy->nb_rsp_cap) {
6431 if (curproxy->mode == PR_MODE_HTTP) {
6432 curproxy->rsp_cap_pool = create_pool("ptrcap",
6433 curproxy->nb_rsp_cap * sizeof(char *),
6434 MEM_F_SHARED);
6435 } else {
6436 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6437 proxy_type_str(curproxy), curproxy->id);
6438 err_code |= ERR_WARN;
6439 curproxy->to_log &= ~LW_REQHDR;
6440 curproxy->nb_rsp_cap = 0;
6441 }
6442 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006443
Willy Tarreau196729e2012-05-31 19:30:26 +02006444 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006445 if (!(curproxy->cap & PR_CAP_FE)) {
6446 if (curproxy->logformat_string != default_http_log_format &&
6447 curproxy->logformat_string != default_tcp_log_format &&
6448 curproxy->logformat_string != clf_http_log_format)
6449 free(curproxy->logformat_string);
6450 curproxy->logformat_string = NULL;
6451 }
6452
Willy Tarreau196729e2012-05-31 19:30:26 +02006453 if (curproxy->logformat_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006454 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY);
Willy Tarreau196729e2012-05-31 19:30:26 +02006455
6456 if (curproxy->uniqueid_format_string)
Willy Tarreau6cbbdbf2013-02-05 18:52:25 +01006457 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0);
Willy Tarreau196729e2012-05-31 19:30:26 +02006458
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 /* first, we will invert the servers list order */
6460 newsrv = NULL;
6461 while (curproxy->srv) {
6462 struct server *next;
6463
6464 next = curproxy->srv->next;
6465 curproxy->srv->next = newsrv;
6466 newsrv = curproxy->srv;
6467 if (!next)
6468 break;
6469 curproxy->srv = next;
6470 }
6471
Willy Tarreaudd701652010-05-25 23:03:02 +02006472 /* assign automatic UIDs to servers which don't have one yet */
6473 next_id = 1;
6474 newsrv = curproxy->srv;
6475 while (newsrv != NULL) {
6476 if (!newsrv->puid) {
6477 /* server ID not set, use automatic numbering with first
6478 * spare entry starting with next_svid.
6479 */
6480 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6481 newsrv->conf.id.key = newsrv->puid = next_id;
6482 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6483 }
6484 next_id++;
6485 newsrv = newsrv->next;
6486 }
6487
Willy Tarreau20697042007-11-15 23:26:18 +01006488 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006489 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006490
Willy Tarreau62c3be22012-01-20 13:12:32 +01006491 /*
6492 * If this server supports a maxconn parameter, it needs a dedicated
6493 * tasks to fill the emptied slots when a connection leaves.
6494 * Also, resolve deferred tracking dependency if needed.
6495 */
6496 newsrv = curproxy->srv;
6497 while (newsrv != NULL) {
6498 if (newsrv->minconn > newsrv->maxconn) {
6499 /* Only 'minconn' was specified, or it was higher than or equal
6500 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6501 * this will avoid further useless expensive computations.
6502 */
6503 newsrv->maxconn = newsrv->minconn;
6504 } else if (newsrv->maxconn && !newsrv->minconn) {
6505 /* minconn was not specified, so we set it to maxconn */
6506 newsrv->minconn = newsrv->maxconn;
6507 }
6508
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006509#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006510 if (newsrv->use_ssl || newsrv->check.use_ssl)
6511 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006512#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006513
Willy Tarreau62c3be22012-01-20 13:12:32 +01006514 if (newsrv->trackit) {
6515 struct proxy *px;
6516 struct server *srv;
6517 char *pname, *sname;
6518
6519 pname = newsrv->trackit;
6520 sname = strrchr(pname, '/');
6521
6522 if (sname)
6523 *sname++ = '\0';
6524 else {
6525 sname = pname;
6526 pname = NULL;
6527 }
6528
6529 if (pname) {
6530 px = findproxy(pname, PR_CAP_BE);
6531 if (!px) {
6532 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6533 proxy_type_str(curproxy), curproxy->id,
6534 newsrv->id, pname);
6535 cfgerr++;
6536 goto next_srv;
6537 }
6538 } else
6539 px = curproxy;
6540
6541 srv = findserver(px, sname);
6542 if (!srv) {
6543 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6544 proxy_type_str(curproxy), curproxy->id,
6545 newsrv->id, sname);
6546 cfgerr++;
6547 goto next_srv;
6548 }
6549
6550 if (!(srv->state & SRV_CHECKED)) {
6551 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6552 "tracking as it does not have checks enabled.\n",
6553 proxy_type_str(curproxy), curproxy->id,
6554 newsrv->id, px->id, srv->id);
6555 cfgerr++;
6556 goto next_srv;
6557 }
6558
6559 if (curproxy != px &&
6560 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6561 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6562 "tracking: disable-on-404 option inconsistency.\n",
6563 proxy_type_str(curproxy), curproxy->id,
6564 newsrv->id, px->id, srv->id);
6565 cfgerr++;
6566 goto next_srv;
6567 }
6568
6569 /* if the other server is forced disabled, we have to do the same here */
6570 if (srv->state & SRV_MAINTAIN) {
6571 newsrv->state |= SRV_MAINTAIN;
6572 newsrv->state &= ~SRV_RUNNING;
6573 newsrv->health = 0;
6574 }
6575
6576 newsrv->track = srv;
6577 newsrv->tracknext = srv->tracknext;
6578 srv->tracknext = newsrv;
6579
6580 free(newsrv->trackit);
6581 newsrv->trackit = NULL;
6582 }
6583 next_srv:
6584 newsrv = newsrv->next;
6585 }
6586
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006587 /* We have to initialize the server lookup mechanism depending
6588 * on what LB algorithm was choosen.
6589 */
6590
6591 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6592 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6593 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006594 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6595 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6596 init_server_map(curproxy);
6597 } else {
6598 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6599 fwrr_init_server_groups(curproxy);
6600 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006601 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006602
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006603 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006604 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6605 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6606 fwlc_init_server_tree(curproxy);
6607 } else {
6608 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6609 fas_init_server_tree(curproxy);
6610 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006611 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006612
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006613 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006614 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6615 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6616 chash_init_server_tree(curproxy);
6617 } else {
6618 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6619 init_server_map(curproxy);
6620 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006621 break;
6622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006623
6624 if (curproxy->options & PR_O_LOGASAP)
6625 curproxy->to_log &= ~LW_BYTES;
6626
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006627 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006628 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006629 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6630 proxy_type_str(curproxy), curproxy->id);
6631 err_code |= ERR_WARN;
6632 }
6633
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006634 if (curproxy->mode != PR_MODE_HTTP) {
6635 int optnum;
6636
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006637 if (curproxy->uri_auth) {
6638 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6639 proxy_type_str(curproxy), curproxy->id);
6640 err_code |= ERR_WARN;
6641 curproxy->uri_auth = NULL;
6642 }
6643
Willy Tarreau87cf5142011-08-19 22:57:24 +02006644 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006645 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6646 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6647 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006648 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006649 }
6650
6651 if (curproxy->options & PR_O_ORGTO) {
6652 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6653 "originalto", proxy_type_str(curproxy), curproxy->id);
6654 err_code |= ERR_WARN;
6655 curproxy->options &= ~PR_O_ORGTO;
6656 }
6657
6658 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6659 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6660 (curproxy->cap & cfg_opts[optnum].cap) &&
6661 (curproxy->options & cfg_opts[optnum].val)) {
6662 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6663 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6664 err_code |= ERR_WARN;
6665 curproxy->options &= ~cfg_opts[optnum].val;
6666 }
6667 }
6668
6669 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6670 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6671 (curproxy->cap & cfg_opts2[optnum].cap) &&
6672 (curproxy->options2 & cfg_opts2[optnum].val)) {
6673 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6674 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6675 err_code |= ERR_WARN;
6676 curproxy->options2 &= ~cfg_opts2[optnum].val;
6677 }
6678 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006679
Willy Tarreauefa5f512010-03-30 20:13:29 +02006680#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006681 if (curproxy->conn_src.bind_hdr_occ) {
6682 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006683 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006684 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006685 err_code |= ERR_WARN;
6686 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006687#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006688 }
6689
Willy Tarreaubaaee002006-06-26 02:48:02 +02006690 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006691 * ensure that we're not cross-dressing a TCP server into HTTP.
6692 */
6693 newsrv = curproxy->srv;
6694 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006695 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006696 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6697 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006698 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006699 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006700
Willy Tarreau0cec3312011-10-31 13:49:26 +01006701 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6702 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6703 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6704 err_code |= ERR_WARN;
6705 }
6706
Willy Tarreauefa5f512010-03-30 20:13:29 +02006707#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006708 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6709 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006710 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 +01006711 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006712 err_code |= ERR_WARN;
6713 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006714#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006715 newsrv = newsrv->next;
6716 }
6717
Willy Tarreauc1a21672009-08-16 22:37:44 +02006718 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006719 if (!curproxy->accept)
6720 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006721
Willy Tarreauc1a21672009-08-16 22:37:44 +02006722 if (curproxy->tcp_req.inspect_delay ||
6723 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006724 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006725
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006726 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006727 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006728 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006729 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006730
6731 /* both TCP and HTTP must check switching rules */
6732 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6733 }
6734
6735 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006736 if (curproxy->tcp_req.inspect_delay ||
6737 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6738 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6739
Emeric Brun97679e72010-09-23 17:56:44 +02006740 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6741 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6742
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006743 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006744 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006745 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006746 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006747
6748 /* If the backend does requires RDP cookie persistence, we have to
6749 * enable the corresponding analyser.
6750 */
6751 if (curproxy->options2 & PR_O2_RDPC_PRST)
6752 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6753 }
6754
Emeric Brunc52962f2012-11-15 18:28:02 +01006755#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006756 /* Configure SSL for each bind line.
6757 * Note: if configuration fails at some point, the ->ctx member
6758 * remains NULL so that listeners can later detach.
6759 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006760 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006761 if (!bind_conf->is_ssl) {
6762 if (bind_conf->default_ctx) {
6763 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6764 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6765 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006766 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006767 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006768 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006769 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006770 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006771 cfgerr++;
6772 continue;
6773 }
6774
Emeric Brun4b3091e2012-09-24 15:48:52 +02006775 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006776 Alert("Unable to allocate SSL session cache.\n");
6777 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006778 continue;
6779 }
6780
Emeric Brunfc0421f2012-09-07 17:30:07 +02006781 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006782 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006783 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006784#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006785
Willy Tarreaue6b98942007-10-29 01:09:36 +01006786 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006787 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006788 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006789 if (!listener->luid) {
6790 /* listener ID not set, use automatic numbering with first
6791 * spare entry starting with next_luid.
6792 */
6793 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6794 listener->conf.id.key = listener->luid = next_id;
6795 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006796 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006797 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006798
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006799 /* enable separate counters */
6800 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6801 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006802 if (!listener->name)
6803 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006804 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006805
Willy Tarreaue6b98942007-10-29 01:09:36 +01006806 if (curproxy->options & PR_O_TCP_NOLING)
6807 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006808 if (!listener->maxconn)
6809 listener->maxconn = curproxy->maxconn;
6810 if (!listener->backlog)
6811 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006812 if (!listener->maxaccept)
6813 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6814
6815 /* we want to have an optimal behaviour on single process mode to
6816 * maximize the work at once, but in multi-process we want to keep
6817 * some fairness between processes, so we target half of the max
6818 * number of events to be balanced over all the processes the proxy
6819 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6820 * used to disable the limit.
6821 */
6822 if (listener->maxaccept > 0) {
6823 if (nbproc > 1)
6824 listener->maxaccept = (listener->maxaccept + 1) / 2;
6825 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6826 }
6827
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006828 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006829 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006830 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006831 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006832
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006833 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6834 listener->options |= LI_O_TCP_RULES;
6835
Willy Tarreaude3041d2010-05-31 10:56:17 +02006836 if (curproxy->mon_mask.s_addr)
6837 listener->options |= LI_O_CHK_MONNET;
6838
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006839 /* smart accept mode is automatic in HTTP mode */
6840 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006841 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006842 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6843 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006844 }
6845
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006846 /* Release unused SSL configs */
6847 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6848 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006849 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006850#ifdef USE_OPENSSL
6851 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006852 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006853 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006854 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006855 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006856#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006857 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006858
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006859 /* Check multi-process mode compatibility for the current proxy */
6860 if (global.nbproc > 1) {
6861 int nbproc = 0;
6862 if (curproxy->bind_proc) {
6863 int proc;
6864 for (proc = 0; proc < global.nbproc; proc++) {
6865 if (curproxy->bind_proc & (1 << proc)) {
6866 nbproc++;
6867 }
6868 }
6869 } else {
6870 nbproc = global.nbproc;
6871 }
6872 if (curproxy->table.peers.name) {
6873 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6874 curproxy->id);
6875 cfgerr++;
6876 }
6877 if (nbproc > 1) {
6878 if (curproxy->uri_auth) {
6879 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6880 curproxy->id);
6881 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6882 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6883 curproxy->id);
6884 }
6885 }
6886 if (curproxy->appsession_name) {
6887 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6888 curproxy->id);
6889 }
6890 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6891 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6892 curproxy->id);
6893 }
6894 }
6895 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006896
6897 /* create the task associated with the proxy */
6898 curproxy->task = task_new();
6899 if (curproxy->task) {
6900 curproxy->task->context = curproxy;
6901 curproxy->task->process = manage_proxy;
6902 /* no need to queue, it will be done automatically if some
6903 * listener gets limited.
6904 */
6905 curproxy->task->expire = TICK_ETERNITY;
6906 } else {
6907 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6908 curproxy->id);
6909 cfgerr++;
6910 }
6911
Willy Tarreaubaaee002006-06-26 02:48:02 +02006912 curproxy = curproxy->next;
6913 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006914
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006915 /* Check multi-process mode compatibility */
6916 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006917 if (global.stats_fe && !global.stats_fe->bind_proc) {
6918 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 +01006919 }
6920 }
6921
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006922 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6923 struct auth_users *curuser;
6924 int g;
6925
6926 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6927 unsigned int group_mask = 0;
6928 char *group = NULL;
6929
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006930 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006931 continue;
6932
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006933 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006934
6935 for (g = 0; g < curuserlist->grpcnt; g++)
6936 if (!strcmp(curuserlist->groups[g], group))
6937 break;
6938
6939 if (g == curuserlist->grpcnt) {
6940 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6941 curuserlist->name, group, curuser->user);
6942 err_code |= ERR_ALERT | ERR_FATAL;
6943 goto out;
6944 }
6945
6946 group_mask |= (1 << g);
6947 }
6948
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006949 free(curuser->u.groups);
6950 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006951 }
6952
6953 for (g = 0; g < curuserlist->grpcnt; g++) {
6954 char *user = NULL;
6955
6956 if (!curuserlist->groupusers[g])
6957 continue;
6958
6959 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6960 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6961 if (!strcmp(curuser->user, user))
6962 break;
6963
6964 if (!curuser) {
6965 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6966 curuserlist->name, user, curuserlist->groups[g]);
6967 err_code |= ERR_ALERT | ERR_FATAL;
6968 goto out;
6969 }
6970
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006971 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006972 }
6973
6974 free(curuserlist->groupusers[g]);
6975 }
6976
6977 free(curuserlist->groupusers);
6978
6979#ifdef DEBUG_AUTH
6980 for (g = 0; g < curuserlist->grpcnt; g++) {
6981 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6982
6983 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006984 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006985 fprintf(stderr, " %s", curuser->user);
6986 }
6987
6988 fprintf(stderr, "\n");
6989 }
6990#endif
6991
Willy Tarreaufbb78422011-06-05 15:38:35 +02006992 }
6993
6994 /* automatically compute fullconn if not set. We must not do it in the
6995 * loop above because cross-references are not yet fully resolved.
6996 */
6997 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6998 /* If <fullconn> is not set, let's set it to 10% of the sum of
6999 * the possible incoming frontend's maxconns.
7000 */
7001 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7002 struct proxy *fe;
7003 int total = 0;
7004
7005 /* sum up the number of maxconns of frontends which
7006 * reference this backend at least once or which are
7007 * the same one ('listen').
7008 */
7009 for (fe = proxy; fe; fe = fe->next) {
7010 struct switching_rule *rule;
7011 struct hdr_exp *exp;
7012 int found = 0;
7013
7014 if (!(fe->cap & PR_CAP_FE))
7015 continue;
7016
7017 if (fe == curproxy) /* we're on a "listen" instance */
7018 found = 1;
7019
7020 if (fe->defbe.be == curproxy) /* "default_backend" */
7021 found = 1;
7022
7023 /* check if a "use_backend" rule matches */
7024 if (!found) {
7025 list_for_each_entry(rule, &fe->switching_rules, list) {
7026 if (rule->be.backend == curproxy) {
7027 found = 1;
7028 break;
7029 }
7030 }
7031 }
7032
7033 /* check if a "reqsetbe" rule matches */
7034 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7035 if (exp->action == ACT_SETBE &&
7036 (struct proxy *)exp->replace == curproxy) {
7037 found = 1;
7038 break;
7039 }
7040 }
7041
7042 /* now we've checked all possible ways to reference a backend
7043 * from a frontend.
7044 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007045 if (!found)
7046 continue;
7047 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007048 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007049 /* we have the sum of the maxconns in <total>. We only
7050 * keep 10% of that sum to set the default fullconn, with
7051 * a hard minimum of 1 (to avoid a divide by zero).
7052 */
7053 curproxy->fullconn = (total + 9) / 10;
7054 if (!curproxy->fullconn)
7055 curproxy->fullconn = 1;
7056 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007057 }
7058
Willy Tarreau056f5682010-06-06 15:51:11 +02007059 /* initialize stick-tables on backend capable proxies. This must not
7060 * be done earlier because the data size may be discovered while parsing
7061 * other proxies.
7062 */
7063 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007064 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007065
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007066 /*
7067 * Recount currently required checks.
7068 */
7069
7070 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7071 int optnum;
7072
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007073 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7074 if (curproxy->options & cfg_opts[optnum].val)
7075 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007076
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007077 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7078 if (curproxy->options2 & cfg_opts2[optnum].val)
7079 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007080 }
7081
Willy Tarreau122541c2011-09-07 21:24:49 +02007082 if (peers) {
7083 struct peers *curpeers = peers, **last;
7084 struct peer *p, *pb;
7085
7086 /* Remove all peers sections which don't have a valid listener.
7087 * This can happen when a peers section is never referenced and
7088 * does not contain a local peer.
7089 */
7090 last = &peers;
7091 while (*last) {
7092 curpeers = *last;
7093 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007094 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007095 last = &curpeers->next;
7096 continue;
7097 }
7098
7099 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7100 curpeers->id, localpeer);
7101
7102 p = curpeers->remote;
7103 while (p) {
7104 pb = p->next;
7105 free(p->id);
7106 free(p);
7107 p = pb;
7108 }
7109
7110 /* Destroy and unlink this curpeers section.
7111 * Note: curpeers is backed up into *last.
7112 */
7113 free(curpeers->id);
7114 curpeers = curpeers->next;
7115 free(*last);
7116 *last = curpeers;
7117 }
7118 }
7119
Willy Tarreau34eb6712011-10-24 18:15:04 +02007120 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007121 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007122 MEM_F_SHARED);
7123
Willy Tarreaubb925012009-07-23 13:36:36 +02007124 if (cfgerr > 0)
7125 err_code |= ERR_ALERT | ERR_FATAL;
7126 out:
7127 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007128}
7129
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007130/*
7131 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7132 * parsing sessions.
7133 */
7134void cfg_register_keywords(struct cfg_kw_list *kwl)
7135{
7136 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7137}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007138
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007139/*
7140 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7141 */
7142void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7143{
7144 LIST_DEL(&kwl->list);
7145 LIST_INIT(&kwl->list);
7146}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007147
7148/*
7149 * Local variables:
7150 * c-indent-level: 8
7151 * c-basic-offset: 8
7152 * End:
7153 */