blob: d1f18f7ab7b8cdc1a34e00f89b0acb7f8fd6cfd3 [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>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020043#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020045#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020054#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020056#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100114struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 const char *name;
116 unsigned int val;
117 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100118 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100119 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100120};
121
122/* proxy->options */
123static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100124{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100125 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
126 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
127 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
129 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
130 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
131 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
135 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
136 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
137 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
138 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
139 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
140 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100141#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100143#else
144 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100145#endif
146
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148};
149
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150/* proxy->options2 */
151static const struct cfg_opt cfg_opts2[] =
152{
153#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
155 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100157#else
158 { "splice-request", 0, 0, 0, 0 },
159 { "splice-response", 0, 0, 0, 0 },
160 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100161#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
163 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
165 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
166 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
167 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
168 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
170 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400171 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200173 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200174 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100175 { NULL, 0, 0, 0 }
176};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177
Willy Tarreau6daf3432008-01-22 16:44:08 +0100178static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
180int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100181int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200183/* List head of all known configuration keywords */
184static struct cfg_kw_list cfg_keywords = {
185 .list = LIST_HEAD_INIT(cfg_keywords.list)
186};
187
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188/*
189 * converts <str> to a list of listeners which are dynamically allocated.
190 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
191 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
192 * - <port> is a numerical port from 1 to 65535 ;
193 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
194 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200195 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
196 * not NULL, it must be a valid pointer to either NULL or a freeable area that
197 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200199int 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 +0200200{
201 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100202 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 int port, end;
204
205 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 while (next && *next) {
208 struct sockaddr_storage ss;
209
210 str = next;
211 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100212 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 *next++ = 0;
214 }
215
Emeric Bruned760922010-10-22 17:59:25 +0200216 if (*str == '/') {
217 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
218 /* so compute max path */
219 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
220 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Emeric Bruned760922010-10-22 17:59:25 +0200222 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200224 goto fail;
225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200228 ss.ss_family = AF_UNIX;
229 if (global.unix_bind.prefix) {
230 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
231 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 }
Emeric Bruned760922010-10-22 17:59:25 +0200233 else {
234 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
235 }
236 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 }
238 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100241 ss2 = str2sa_range(str, &port, &end);
242 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 /* OK the address looks correct */
253 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Emeric Bruned760922010-10-22 17:59:25 +0200255 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200256 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
265
266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200268 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
269 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
270 l->frontend = curproxy;
271 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
273 l->fd = -1;
274 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200275 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100276 l->state = LI_INIT;
277
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100278 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100280 tcpv4_add_listener(l);
281 }
Emeric Bruned760922010-10-22 17:59:25 +0200282 else if (ss.ss_family == AF_INET6) {
283 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
284 tcpv6_add_listener(l);
285 }
286 else {
Emeric Bruned760922010-10-22 17:59:25 +0200287 uxst_add_listener(l);
288 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200290 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100291 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 } /* end for(port) */
293 } /* end while(next) */
294 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200295 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 fail:
297 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299}
300
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301/*
302 * Sends a warning if proxy <proxy> does not have at least one of the
303 * capabilities in <cap>. An optionnal <hint> may be added at the end
304 * of the warning to help the user. Returns 1 if a warning was emitted
305 * or 0 if the condition is valid.
306 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100307int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100308{
309 char *msg;
310
311 switch (cap) {
312 case PR_CAP_BE: msg = "no backend"; break;
313 case PR_CAP_FE: msg = "no frontend"; break;
314 case PR_CAP_RS: msg = "no ruleset"; break;
315 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
316 default: msg = "not enough"; break;
317 }
318
319 if (!(proxy->cap & cap)) {
320 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100321 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100322 return 1;
323 }
324 return 0;
325}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326
Willy Tarreau61d18892009-03-31 10:49:21 +0200327/* Report a warning if a rule is placed after a 'block' rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100330int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200331{
332 if (!LIST_ISEMPTY(&proxy->block_cond)) {
333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a reqrewrite rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100343int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200344{
345 if (proxy->req_exp) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a reqadd rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100356int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200357{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100358 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* Report a warning if a rule is placed after a redirect rule.
367 * Return 1 if the warning has been emitted, otherwise 0.
368 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
372 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
373 file, line, arg);
374 return 1;
375 }
376 return 0;
377}
378
379/* Report a warning if a rule is placed after a 'use_backend' rule.
380 * Return 1 if the warning has been emitted, otherwise 0.
381 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
385 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
386 file, line, arg);
387 return 1;
388 }
389 return 0;
390}
391
392/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
396 warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
405 warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
409/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
412 return warnif_rule_after_redirect(proxy, file, line, arg) ||
413 warnif_rule_after_use_backend(proxy, file, line, arg);
414}
415
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100416/* Report it if a request ACL condition uses some response-only parameters. It
417 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
418 * Note that <cond> may be NULL and then will be ignored.
419 */
420static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
421{
422 struct acl *acl;
423
424 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
425 return 0;
426
427 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
428 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
429 file, line, acl ? acl->name : "(unknown)");
430 return ERR_WARN;
431}
432
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100433/* Report it if a request ACL condition uses some request-only volatile parameters.
434 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
435 * Note that <cond> may be NULL and then will be ignored.
436 */
437static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
438{
439 struct acl *acl;
440
441 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
442 return 0;
443
444 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
445 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
446 file, line, acl ? acl->name : "(unknown)");
447 return ERR_WARN;
448}
449
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200452 * parse a line in a <global> section. Returns the error code, 0 if OK, or
453 * any combination of :
454 * - ERR_ABORT: must abort ASAP
455 * - ERR_FATAL: we can continue parsing but not start the service
456 * - ERR_WARN: a warning has been emitted
457 * - ERR_ALERT: an alert has been emitted
458 * Only the two first ones can stop processing, the two others are just
459 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200461int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462{
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200464 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465
466 if (!strcmp(args[0], "global")) { /* new section */
467 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200470 else if (!strcmp(args[0], "ca-base")) {
471#ifdef USE_OPENSSL
472 if (global.ca_base != NULL) {
473 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
474 err_code |= ERR_ALERT;
475 goto out;
476 }
477 if (*(args[1]) == 0) {
478 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
479 err_code |= ERR_ALERT | ERR_FATAL;
480 goto out;
481 }
482 global.ca_base = strdup(args[1]);
483#else
484 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
485 err_code |= ERR_ALERT | ERR_FATAL;
486 goto out;
487#endif
488 }
489 else if (!strcmp(args[0], "crt-base")) {
490#ifdef USE_OPENSSL
491 if (global.crt_base != NULL) {
492 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
493 err_code |= ERR_ALERT;
494 goto out;
495 }
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.crt_base = strdup(args[1]);
502#else
503 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
506#endif
507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 else if (!strcmp(args[0], "daemon")) {
509 global.mode |= MODE_DAEMON;
510 }
511 else if (!strcmp(args[0], "debug")) {
512 global.mode |= MODE_DEBUG;
513 }
514 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100515 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200516 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100518 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 }
520 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100521 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100524 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100526 else if (!strcmp(args[0], "nosplice")) {
527 global.tune.options &= ~GTUNE_USE_SPLICE;
528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 else if (!strcmp(args[0], "quiet")) {
530 global.mode |= MODE_QUIET;
531 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 else if (!strcmp(args[0], "tune.maxpollevents")) {
533 if (global.tune.maxpollevents != 0) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200542 }
543 global.tune.maxpollevents = atol(args[1]);
544 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 else if (!strcmp(args[0], "tune.maxaccept")) {
546 if (global.tune.maxaccept != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100555 }
556 global.tune.maxaccept = atol(args[1]);
557 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200558 else if (!strcmp(args[0], "tune.chksize")) {
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.chksize = atol(args[1]);
565 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566#ifdef USE_OPENSSL
567 else if (!strcmp(args[0], "tune.sslcachesize")) {
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
572 }
573 global.tune.sslcachesize = atol(args[1]);
574 }
575#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200576 else if (!strcmp(args[0], "tune.bufsize")) {
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.bufsize = atol(args[1]);
583 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
584 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100585 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200586 }
587 else if (!strcmp(args[0], "tune.maxrewrite")) {
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
592 }
593 global.tune.maxrewrite = atol(args[1]);
594 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
595 global.tune.maxrewrite = global.tune.bufsize / 2;
596 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100597 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
598 if (global.tune.client_rcvbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.client_rcvbuf = atol(args[1]);
609 }
610 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
611 if (global.tune.server_rcvbuf != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.server_rcvbuf = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "tune.sndbuf.client")) {
624 if (global.tune.client_sndbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_sndbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.sndbuf.server")) {
637 if (global.tune.server_sndbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_sndbuf = atol(args[1]);
648 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200649 else if (!strcmp(args[0], "tune.pipesize")) {
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.pipesize = atol(args[1]);
656 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200657 else if (!strcmp(args[0], "tune.http.maxhdr")) {
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
662 }
663 global.tune.max_http_hdr = atol(args[1]);
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "uid")) {
666 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.uid = atol(args[1]);
677 }
678 else if (!strcmp(args[0], "gid")) {
679 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200680 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 global.gid = atol(args[1]);
690 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200691 /* user/group name handling */
692 else if (!strcmp(args[0], "user")) {
693 struct passwd *ha_user;
694 if (global.uid != 0) {
695 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200698 }
699 errno = 0;
700 ha_user = getpwnam(args[1]);
701 if (ha_user != NULL) {
702 global.uid = (int)ha_user->pw_uid;
703 }
704 else {
705 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 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200707 }
708 }
709 else if (!strcmp(args[0], "group")) {
710 struct group *ha_group;
711 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200712 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT;
714 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200715 }
716 errno = 0;
717 ha_group = getgrnam(args[1]);
718 if (ha_group != NULL) {
719 global.gid = (int)ha_group->gr_gid;
720 }
721 else {
722 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 +0200723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200724 }
725 }
726 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 else if (!strcmp(args[0], "nbproc")) {
728 if (global.nbproc != 0) {
729 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 }
738 global.nbproc = atol(args[1]);
739 }
740 else if (!strcmp(args[0], "maxconn")) {
741 if (global.maxconn != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
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.maxconn = atol(args[1]);
752#ifdef SYSTEM_MAXCONN
753 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
754 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);
755 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758#endif /* SYSTEM_MAXCONN */
759 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200760 else if (!strcmp(args[0], "maxsslconn")) {
761#ifdef USE_OPENSSL
762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.maxsslconn = atol(args[1]);
768#else
Emeric Brun0914df82012-10-02 18:45:42 +0200769 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200772#endif
773 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200774 else if (!strcmp(args[0], "maxconnrate")) {
775 if (global.cps_lim != 0) {
776 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT;
778 goto out;
779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.cps_lim = atol(args[1]);
786 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100787 else if (!strcmp(args[0], "maxpipes")) {
788 if (global.maxpipes != 0) {
789 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100792 }
793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100797 }
798 global.maxpipes = atol(args[1]);
799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 else if (!strcmp(args[0], "ulimit-n")) {
801 if (global.rlimit_nofile != 0) {
802 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200810 }
811 global.rlimit_nofile = atol(args[1]);
812 }
813 else if (!strcmp(args[0], "chroot")) {
814 if (global.chroot != NULL) {
815 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200816 err_code |= ERR_ALERT;
817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 }
824 global.chroot = strdup(args[1]);
825 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200826 else if (!strcmp(args[0], "description")) {
827 int i, len=0;
828 char *d;
829
830 if (!*args[1]) {
831 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
832 file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 for(i=1; *args[i]; i++)
838 len += strlen(args[i])+1;
839
840 if (global.desc)
841 free(global.desc);
842
843 global.desc = d = (char *)calloc(1, len);
844
845 d += sprintf(d, "%s", args[1]);
846 for(i=2; *args[i]; i++)
847 d += sprintf(d, " %s", args[i]);
848 }
849 else if (!strcmp(args[0], "node")) {
850 int i;
851 char c;
852
853 for (i=0; args[1][i]; i++) {
854 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100855 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
856 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200857 break;
858 }
859
860 if (!i || args[1][i]) {
861 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
862 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
863 file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 if (global.node)
869 free(global.node);
870
871 global.node = strdup(args[1]);
872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 else if (!strcmp(args[0], "pidfile")) {
874 if (global.pidfile != NULL) {
875 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200876 err_code |= ERR_ALERT;
877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 }
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 }
884 global.pidfile = strdup(args[1]);
885 }
Emeric Bruned760922010-10-22 17:59:25 +0200886 else if (!strcmp(args[0], "unix-bind")) {
887 int cur_arg = 1;
888 while (*(args[cur_arg])) {
889 if (!strcmp(args[cur_arg], "prefix")) {
890 if (global.unix_bind.prefix != NULL) {
891 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
892 err_code |= ERR_ALERT;
893 cur_arg += 2;
894 continue;
895 }
896
897 if (*(args[cur_arg+1]) == 0) {
898 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.unix_bind.prefix = strdup(args[cur_arg+1]);
903 cur_arg += 2;
904 continue;
905 }
906
907 if (!strcmp(args[cur_arg], "mode")) {
908
909 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
910 cur_arg += 2;
911 continue;
912 }
913
914 if (!strcmp(args[cur_arg], "uid")) {
915
916 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
917 cur_arg += 2;
918 continue;
919 }
920
921 if (!strcmp(args[cur_arg], "gid")) {
922
923 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
924 cur_arg += 2;
925 continue;
926 }
927
928 if (!strcmp(args[cur_arg], "user")) {
929 struct passwd *user;
930
931 user = getpwnam(args[cur_arg + 1]);
932 if (!user) {
933 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
934 file, linenum, args[0], args[cur_arg + 1 ]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938
939 global.unix_bind.ux.uid = user->pw_uid;
940 cur_arg += 2;
941 continue;
942 }
943
944 if (!strcmp(args[cur_arg], "group")) {
945 struct group *group;
946
947 group = getgrnam(args[cur_arg + 1]);
948 if (!group) {
949 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
950 file, linenum, args[0], args[cur_arg + 1 ]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954
955 global.unix_bind.ux.gid = group->gr_gid;
956 cur_arg += 2;
957 continue;
958 }
959
Willy Tarreaub48f9582011-09-05 01:17:06 +0200960 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200961 file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 }
William Lallemand0f99e342011-10-12 17:50:54 +0200966 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
967 /* delete previous herited or defined syslog servers */
968 struct logsrv *back;
969 struct logsrv *tmp;
970
971 if (*(args[1]) != 0) {
972 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
976
977 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
978 LIST_DEL(&tmp->list);
979 free(tmp);
980 }
981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200983 struct logsrv *logsrv;
984
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 if (*(args[1]) == 0 || *(args[2]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 }
William Lallemand0f99e342011-10-12 17:50:54 +0200990
991 logsrv = calloc(1, sizeof(struct logsrv));
992
993 logsrv->facility = get_log_facility(args[2]);
994 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200997 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999
William Lallemand0f99e342011-10-12 17:50:54 +02001000 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001002 logsrv->level = get_log_level(args[3]);
1003 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001006 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 }
1009
William Lallemand0f99e342011-10-12 17:50:54 +02001010 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001011 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001012 logsrv->minlvl = get_log_level(args[4]);
1013 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001014 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001016 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001017 }
1018 }
1019
Robert Tsai81ae1952007-12-05 10:47:29 +01001020 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001021 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001022 if (!sk) {
1023 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001024 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001025 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001026 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001027 goto out;
1028 }
William Lallemand0f99e342011-10-12 17:50:54 +02001029 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001030 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001031 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001032 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001033 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001035 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001036 goto out;
1037 }
William Lallemand0f99e342011-10-12 17:50:54 +02001038 logsrv->addr = *sk;
1039 if (!get_host_port(&logsrv->addr))
1040 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042
William Lallemand0f99e342011-10-12 17:50:54 +02001043 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001044 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001045 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1046 char *name;
1047 int len;
1048
1049 if (global.log_send_hostname != NULL) {
1050 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT;
1052 goto out;
1053 }
1054
1055 if (*(args[1]))
1056 name = args[1];
1057 else
1058 name = hostname;
1059
1060 len = strlen(name);
1061
1062 /* We'll add a space after the name to respect the log format */
1063 free(global.log_send_hostname);
1064 global.log_send_hostname = malloc(len + 2);
1065 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1066 }
Kevinm48936af2010-12-22 16:08:21 +00001067 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 free(global.log_tag);
1074 global.log_tag = strdup(args[1]);
1075 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001076 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1077 if (global.spread_checks != 0) {
1078 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
1080 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001081 }
1082 if (*(args[1]) == 0) {
1083 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001084 err_code |= ERR_ALERT | ERR_FATAL;
1085 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001086 }
1087 global.spread_checks = atol(args[1]);
1088 if (global.spread_checks < 0 || global.spread_checks > 50) {
1089 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001094 struct cfg_kw_list *kwl;
1095 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001096 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001097
1098 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1099 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1100 if (kwl->kw[index].section != CFG_GLOBAL)
1101 continue;
1102 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001103 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001104 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001105 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001107 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001108 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001109 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001110 err_code |= ERR_WARN;
1111 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001112 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001113 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001114 }
1115 }
1116 }
1117
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001119 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001121
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001123 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001124 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125}
1126
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001127void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001129 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 defproxy.mode = PR_MODE_TCP;
1131 defproxy.state = PR_STNEW;
1132 defproxy.maxconn = cfg_maxpconn;
1133 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001134
1135 defproxy.defsrv.inter = DEF_CHKINTR;
1136 defproxy.defsrv.fastinter = 0;
1137 defproxy.defsrv.downinter = 0;
1138 defproxy.defsrv.rise = DEF_RISETIME;
1139 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001140 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001141 defproxy.defsrv.maxqueue = 0;
1142 defproxy.defsrv.minconn = 0;
1143 defproxy.defsrv.maxconn = 0;
1144 defproxy.defsrv.slowstart = 0;
1145 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1146 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1147 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148}
1149
Willy Tarreauade5ec42010-01-28 19:33:49 +01001150
1151static int create_cond_regex_rule(const char *file, int line,
1152 struct proxy *px, int dir, int action, int flags,
1153 const char *cmd, const char *reg, const char *repl,
1154 const char **cond_start)
1155{
1156 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001157 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001158 const char *err;
1159 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001160 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001161
1162 if (px == &defproxy) {
1163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto err;
1166 }
1167
1168 if (*reg == 0) {
1169 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto err;
1172 }
1173
1174 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1175 err_code |= ERR_WARN;
1176
Willy Tarreau5321c422010-01-28 20:35:13 +01001177 if (cond_start &&
1178 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001179 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1180 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1181 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto err;
1184 }
1185 }
1186 else if (cond_start && **cond_start) {
1187 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1188 file, line, cmd, *cond_start);
1189 err_code |= ERR_ALERT | ERR_FATAL;
1190 goto err;
1191 }
1192
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001193 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001194 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001195 else
1196 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001197
Willy Tarreauade5ec42010-01-28 19:33:49 +01001198 preg = calloc(1, sizeof(regex_t));
1199 if (!preg) {
1200 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1201 err_code = ERR_ALERT | ERR_FATAL;
1202 goto err;
1203 }
1204
1205 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1206 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1207 err_code = ERR_ALERT | ERR_FATAL;
1208 goto err;
1209 }
1210
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001211 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001212 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001213 if (repl && err) {
1214 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1215 file, line, cmd, *err);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto err;
1218 }
1219
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001220 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001221 err_code |= ERR_WARN;
1222
Willy Tarreauf4068b62012-05-08 17:37:49 +02001223 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001224 return err_code;
1225 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001226 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001227 free(preg);
1228 return err_code;
1229}
1230
Willy Tarreaubaaee002006-06-26 02:48:02 +02001231/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001232 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001233 * Returns the error code, 0 if OK, or any combination of :
1234 * - ERR_ABORT: must abort ASAP
1235 * - ERR_FATAL: we can continue parsing but not start the service
1236 * - ERR_WARN: a warning has been emitted
1237 * - ERR_ALERT: an alert has been emitted
1238 * Only the two first ones can stop processing, the two others are just
1239 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001240 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001241int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1242{
1243 static struct peers *curpeers = NULL;
1244 struct peer *newpeer = NULL;
1245 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001246 struct bind_conf *bind_conf;
1247 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001248 int err_code = 0;
1249
1250 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1251
1252 err = invalid_char(args[1]);
1253 if (err) {
1254 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1255 file, linenum, *err, args[0], args[1]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 }
1258
1259 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1260 /*
1261 * If there are two proxies with the same name only following
1262 * combinations are allowed:
1263 */
1264 if (strcmp(curpeers->id, args[1]) == 0) {
1265 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1266 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1267 err_code |= ERR_WARN;
1268 }
1269 }
1270
1271 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1273 err_code |= ERR_ALERT | ERR_ABORT;
1274 goto out;
1275 }
1276
1277 curpeers->next = peers;
1278 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001279 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001280 curpeers->conf.line = linenum;
1281 curpeers->last_change = now.tv_sec;
1282 curpeers->id = strdup(args[1]);
1283 }
1284 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1285 char *rport, *raddr;
1286 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001287 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001288 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001289
1290 if (!*args[2]) {
1291 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1292 file, linenum, args[0]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296
1297 err = invalid_char(args[1]);
1298 if (err) {
1299 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1300 file, linenum, *err, args[1]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
1305 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1306 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1307 err_code |= ERR_ALERT | ERR_ABORT;
1308 goto out;
1309 }
1310
1311 /* the peers are linked backwards first */
1312 curpeers->count++;
1313 newpeer->next = curpeers->remote;
1314 curpeers->remote = newpeer;
1315 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001316 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001317 newpeer->conf.line = linenum;
1318
1319 newpeer->last_change = now.tv_sec;
1320 newpeer->id = strdup(args[1]);
1321
1322 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001323 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001324 if (rport) {
1325 *rport++ = 0;
1326 realport = atol(rport);
1327 }
1328 if (!realport) {
1329 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
Willy Tarreaufab5a432011-03-04 15:31:53 +01001334 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001335 free(raddr);
1336 if (!sk) {
1337 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1338 err_code |= ERR_ALERT | ERR_FATAL;
1339 goto out;
1340 }
1341 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001342 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001343 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001344 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001345
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001346 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001347 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1348 file, linenum, newpeer->addr.ss_family, args[2]);
1349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
1351 }
1352
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001353 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001354
1355 if (strcmp(newpeer->id, localpeer) == 0) {
1356 /* Current is local peer, it define a frontend */
1357 newpeer->local = 1;
1358
1359 if (!curpeers->peers_fe) {
1360 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1362 err_code |= ERR_ALERT | ERR_ABORT;
1363 goto out;
1364 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001365
Willy Tarreau237250c2011-07-29 01:49:03 +02001366 init_new_proxy(curpeers->peers_fe);
1367 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001368
1369 curpeers->peers_fe->last_change = now.tv_sec;
1370 curpeers->peers_fe->id = strdup(args[1]);
1371 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001372 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001373 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1374 curpeers->peers_fe->timeout.connect = 5000;
1375 curpeers->peers_fe->accept = peer_accept;
1376 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001377
1378 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1379
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001380 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1381 if (err_msg && *err_msg) {
1382 indent_msg(&err_msg, 2);
1383 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1384 }
1385 else
1386 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1387 file, linenum, args[0], args[1], args[2]);
1388 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001389 err_code |= ERR_FATAL;
1390 goto out;
1391 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001392
1393 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1394 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1395 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1396 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1397 l->accept = session_accept;
1398 l->handler = process_session;
1399 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1400 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1401 global.maxsock += l->maxconn;
1402 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001403 }
1404 }
1405 } /* neither "peer" nor "peers" */
1406 else if (*args[0] != 0) {
1407 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1408 err_code |= ERR_ALERT | ERR_FATAL;
1409 goto out;
1410 }
1411
1412out:
1413 return err_code;
1414}
1415
1416
Willy Tarreau3842f002009-06-14 11:39:52 +02001417int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418{
1419 static struct proxy *curproxy = NULL;
1420 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001421 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001422 int rc;
1423 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001424 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001425 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001426 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001427 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001428 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429
Willy Tarreau977b8e42006-12-29 14:19:17 +01001430 if (!strcmp(args[0], "listen"))
1431 rc = PR_CAP_LISTEN;
1432 else if (!strcmp(args[0], "frontend"))
1433 rc = PR_CAP_FE | PR_CAP_RS;
1434 else if (!strcmp(args[0], "backend"))
1435 rc = PR_CAP_BE | PR_CAP_RS;
1436 else if (!strcmp(args[0], "ruleset"))
1437 rc = PR_CAP_RS;
1438 else
1439 rc = PR_CAP_NONE;
1440
1441 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442 if (!*args[1]) {
1443 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1444 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001446 err_code |= ERR_ALERT | ERR_ABORT;
1447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001449
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001450 err = invalid_char(args[1]);
1451 if (err) {
1452 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1453 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001454 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001455 }
1456
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001457 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1458 /*
1459 * If there are two proxies with the same name only following
1460 * combinations are allowed:
1461 *
1462 * listen backend frontend ruleset
1463 * listen - - - -
1464 * backend - - OK -
1465 * frontend - OK - -
1466 * ruleset - - - -
1467 */
1468
1469 if (!strcmp(curproxy->id, args[1]) &&
1470 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1471 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001472 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1473 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1474 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001475 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001476 }
1477 }
1478
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1480 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001481 err_code |= ERR_ALERT | ERR_ABORT;
1482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001484
Willy Tarreau97cb7802010-01-03 20:23:58 +01001485 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 curproxy->next = proxy;
1487 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001488 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001489 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001490 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
1494 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001496 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001497 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001498
Willy Tarreau4348fad2012-09-20 16:48:07 +02001499 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1500
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001501 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1502 if (err_msg && *err_msg) {
1503 indent_msg(&err_msg, 2);
1504 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1505 }
1506 else
1507 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1508 file, linenum, args[0], args[1], args[2]);
1509 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001510 err_code |= ERR_FATAL;
1511 goto out;
1512 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001513
Willy Tarreau4348fad2012-09-20 16:48:07 +02001514 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001515 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001517 }
1518
1519 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001520 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001521 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001525 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001526 curproxy->no_options = defproxy.no_options;
1527 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001528 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001529 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001530 curproxy->except_net = defproxy.except_net;
1531 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001532 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001533 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001535 if (defproxy.fwdfor_hdr_len) {
1536 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1537 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1538 }
1539
Willy Tarreaub86db342009-11-30 11:50:16 +01001540 if (defproxy.orgto_hdr_len) {
1541 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1542 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1543 }
1544
Mark Lamourinec2247f02012-01-04 13:02:01 -05001545 if (defproxy.server_id_hdr_len) {
1546 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1547 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1548 }
1549
Willy Tarreau977b8e42006-12-29 14:19:17 +01001550 if (curproxy->cap & PR_CAP_FE) {
1551 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001552 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001553 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001554
1555 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001556 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1557 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558
1559 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561
Willy Tarreau977b8e42006-12-29 14:19:17 +01001562 if (curproxy->cap & PR_CAP_BE) {
1563 curproxy->fullconn = defproxy.fullconn;
1564 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001566 if (defproxy.check_req) {
1567 curproxy->check_req = calloc(1, defproxy.check_len);
1568 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1569 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001570 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001572 if (defproxy.expect_str) {
1573 curproxy->expect_str = strdup(defproxy.expect_str);
1574 if (defproxy.expect_regex) {
1575 /* note: this regex is known to be valid */
1576 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1577 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1578 }
1579 }
1580
Willy Tarreau67402132012-05-31 20:40:20 +02001581 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001582 if (defproxy.cookie_name)
1583 curproxy->cookie_name = strdup(defproxy.cookie_name);
1584 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001585 if (defproxy.cookie_domain)
1586 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001587
Willy Tarreau31936852010-10-06 16:59:56 +02001588 if (defproxy.cookie_maxidle)
1589 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1590
1591 if (defproxy.cookie_maxlife)
1592 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1593
Emeric Brun647caf12009-06-30 17:57:00 +02001594 if (defproxy.rdp_cookie_name)
1595 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1596 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1597
Willy Tarreau01732802007-11-01 22:48:15 +01001598 if (defproxy.url_param_name)
1599 curproxy->url_param_name = strdup(defproxy.url_param_name);
1600 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001601
Benoitaffb4812009-03-25 13:02:10 +01001602 if (defproxy.hh_name)
1603 curproxy->hh_name = strdup(defproxy.hh_name);
1604 curproxy->hh_len = defproxy.hh_len;
1605 curproxy->hh_match_domain = defproxy.hh_match_domain;
1606
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001607 if (defproxy.iface_name)
1608 curproxy->iface_name = strdup(defproxy.iface_name);
1609 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001612 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001613 if (defproxy.capture_name)
1614 curproxy->capture_name = strdup(defproxy.capture_name);
1615 curproxy->capture_namelen = defproxy.capture_namelen;
1616 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618
Willy Tarreau977b8e42006-12-29 14:19:17 +01001619 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001620 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001621 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001622 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001623 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001624 curproxy->uri_auth = defproxy.uri_auth;
1625 curproxy->mon_net = defproxy.mon_net;
1626 curproxy->mon_mask = defproxy.mon_mask;
1627 if (defproxy.monitor_uri)
1628 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1629 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001630 if (defproxy.defbe.name)
1631 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001632
1633 /* get either a pointer to the logformat string or a copy of it */
1634 curproxy->logformat_string = defproxy.logformat_string;
1635 if (curproxy->logformat_string &&
1636 curproxy->logformat_string != default_http_log_format &&
1637 curproxy->logformat_string != default_tcp_log_format &&
1638 curproxy->logformat_string != clf_http_log_format)
1639 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001640 }
1641
1642 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001643 curproxy->timeout.connect = defproxy.timeout.connect;
1644 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001645 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001646 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001647 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001648 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001649 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001650 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651 curproxy->source_addr = defproxy.source_addr;
1652 }
1653
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001655
1656 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001657 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001658 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001659 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001660 LIST_INIT(&node->list);
1661 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1662 }
1663
Willy Tarreau196729e2012-05-31 19:30:26 +02001664 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1665 if (curproxy->uniqueid_format_string)
1666 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001667
1668 /* copy default header unique id */
1669 if (defproxy.header_unique_id)
1670 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1671
William Lallemand82fe75c2012-10-23 10:25:10 +02001672 /* default compression options */
1673 if (defproxy.comp != NULL) {
1674 curproxy->comp = calloc(1, sizeof(struct comp));
1675 curproxy->comp->algos = defproxy.comp->algos;
1676 curproxy->comp->types = defproxy.comp->types;
1677 }
1678
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001680 curproxy->conf.used_listener_id = EB_ROOT;
1681 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001682
Willy Tarreau93893792009-07-23 13:19:11 +02001683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 }
1685 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1686 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001687 /* FIXME-20070101: we should do this too at the end of the
1688 * config parsing to free all default values.
1689 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001690 free(defproxy.check_req);
1691 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001692 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001693 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001694 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001695 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001696 free(defproxy.capture_name);
1697 free(defproxy.monitor_uri);
1698 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001699 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001700 free(defproxy.fwdfor_hdr_name);
1701 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001702 free(defproxy.orgto_hdr_name);
1703 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001704 free(defproxy.server_id_hdr_name);
1705 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001706 free(defproxy.expect_str);
1707 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001708
Willy Tarreau39b06652012-06-01 10:58:06 +02001709 if (defproxy.logformat_string != default_http_log_format &&
1710 defproxy.logformat_string != default_tcp_log_format &&
1711 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001712 free(defproxy.logformat_string);
1713
1714 free(defproxy.uniqueid_format_string);
1715
Willy Tarreaua534fea2008-08-03 12:19:50 +02001716 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001717 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001718
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 /* we cannot free uri_auth because it might already be used */
1720 init_default_instance();
1721 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001722 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 }
1725 else if (curproxy == NULL) {
1726 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 }
1730
Willy Tarreau977b8e42006-12-29 14:19:17 +01001731
1732 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001734 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001735 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001736 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001737
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 if (curproxy == &defproxy) {
1739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001743 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745
Emeric Bruned760922010-10-22 17:59:25 +02001746 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001747 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001752
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001753 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001754 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001755
1756 /* NOTE: the following line might create several listeners if there
1757 * are comma-separated IPs or port ranges. So all further processing
1758 * will have to be applied to all listeners created after last_listen.
1759 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001760 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1761 if (err_msg && *err_msg) {
1762 indent_msg(&err_msg, 2);
1763 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1764 }
1765 else
1766 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1767 file, linenum, args[0], args[1]);
1768 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001772
Willy Tarreau4348fad2012-09-20 16:48:07 +02001773 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1774 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001775 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001776 }
1777
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001778 cur_arg = 2;
1779 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001780 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001781 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001782 char *err;
1783
Willy Tarreau26982662012-09-12 23:17:10 +02001784 kw = bind_find_kw(args[cur_arg]);
1785 if (kw) {
1786 char *err = NULL;
1787 int code;
1788
1789 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001790 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1791 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001792 cur_arg += 1 + kw->skip ;
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
Willy Tarreau4348fad2012-09-20 16:48:07 +02001797 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001798 err_code |= code;
1799
1800 if (code) {
1801 if (err && *err) {
1802 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001803 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001804 }
1805 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001806 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1807 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001808 if (code & ERR_FATAL) {
1809 free(err);
1810 cur_arg += 1 + kw->skip;
1811 goto out;
1812 }
1813 }
1814 free(err);
1815 cur_arg += 1 + kw->skip;
1816 continue;
1817 }
1818
Willy Tarreau8638f482012-09-18 18:01:17 +02001819 err = NULL;
1820 if (!bind_dumped) {
1821 bind_dump_kws(&err);
1822 indent_msg(&err, 4);
1823 bind_dumped = 1;
1824 }
1825
1826 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1827 file, linenum, args[0], args[1], args[cur_arg],
1828 err ? " Registered keywords :" : "", err ? err : "");
1829 free(err);
1830
Willy Tarreau93893792009-07-23 13:19:11 +02001831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001833 }
Willy Tarreau93893792009-07-23 13:19:11 +02001834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 }
1836 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1837 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1838 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1839 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001843 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846 /* flush useless bits */
1847 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001850 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001851 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001852 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853
Willy Tarreau1c47f852006-07-09 08:22:27 +02001854 if (!*args[1]) {
1855 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001859 }
1860
Willy Tarreaua534fea2008-08-03 12:19:50 +02001861 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001862 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001863 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001864 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001865 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1866
Willy Tarreau93893792009-07-23 13:19:11 +02001867 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1870 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1871 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1872 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1873 else {
1874 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 }
1878 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001879 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001880 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001881
1882 if (curproxy == &defproxy) {
1883 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001887 }
1888
1889 if (!*args[1]) {
1890 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1891 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001894 }
1895
1896 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001897 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001898
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001899 if (curproxy->uuid <= 0) {
1900 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001901 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001904 }
1905
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001906 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1907 if (node) {
1908 struct proxy *target = container_of(node, struct proxy, conf.id);
1909 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1910 file, linenum, proxy_type_str(curproxy), curproxy->id,
1911 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
1914 }
1915 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001916 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001917 else if (!strcmp(args[0], "description")) {
1918 int i, len=0;
1919 char *d;
1920
Cyril Bonté99ed3272010-01-24 23:29:44 +01001921 if (curproxy == &defproxy) {
1922 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1923 file, linenum, args[0]);
1924 err_code |= ERR_ALERT | ERR_FATAL;
1925 goto out;
1926 }
1927
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001928 if (!*args[1]) {
1929 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1930 file, linenum, args[0]);
1931 return -1;
1932 }
1933
1934 for(i=1; *args[i]; i++)
1935 len += strlen(args[i])+1;
1936
1937 d = (char *)calloc(1, len);
1938 curproxy->desc = d;
1939
1940 d += sprintf(d, "%s", args[1]);
1941 for(i=2; *args[i]; i++)
1942 d += sprintf(d, " %s", args[i]);
1943
1944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1946 curproxy->state = PR_STSTOPPED;
1947 }
1948 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1949 curproxy->state = PR_STNEW;
1950 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001951 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1952 int cur_arg = 1;
1953 unsigned int set = 0;
1954
1955 while (*args[cur_arg]) {
1956 int u;
1957 if (strcmp(args[cur_arg], "all") == 0) {
1958 set = 0;
1959 break;
1960 }
1961 else if (strcmp(args[cur_arg], "odd") == 0) {
1962 set |= 0x55555555;
1963 }
1964 else if (strcmp(args[cur_arg], "even") == 0) {
1965 set |= 0xAAAAAAAA;
1966 }
1967 else {
1968 u = str2uic(args[cur_arg]);
1969 if (u < 1 || u > 32) {
1970 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1971 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001974 }
1975 if (u > global.nbproc) {
1976 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1977 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001979 }
1980 set |= 1 << (u - 1);
1981 }
1982 cur_arg++;
1983 }
1984 curproxy->bind_proc = set;
1985 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001986 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001987 if (curproxy == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001991 }
1992
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001993 err = invalid_char(args[1]);
1994 if (err) {
1995 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1996 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001997 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001998 }
1999
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002000 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2001 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2002 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002005 }
2006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002007 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2008 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009
Willy Tarreau977b8e42006-12-29 14:19:17 +01002010 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 if (*(args[1]) == 0) {
2014 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002019
Willy Tarreau67402132012-05-31 20:40:20 +02002020 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002021 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002022 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002023 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 curproxy->cookie_name = strdup(args[1]);
2025 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 cur_arg = 2;
2028 while (*(args[cur_arg])) {
2029 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002030 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 }
2032 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002033 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 }
2035 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002036 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 }
2038 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002039 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 }
2041 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002042 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002044 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002045 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002048 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002050 else if (!strcmp(args[cur_arg], "httponly")) {
2051 curproxy->ck_opts |= PR_CK_HTTPONLY;
2052 }
2053 else if (!strcmp(args[cur_arg], "secure")) {
2054 curproxy->ck_opts |= PR_CK_SECURE;
2055 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002056 else if (!strcmp(args[cur_arg], "domain")) {
2057 if (!*args[cur_arg + 1]) {
2058 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2059 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002062 }
2063
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002064 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002065 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002066 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2067 " dots nor does not start with a dot."
2068 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002069 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002070 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002071 }
2072
2073 err = invalid_domainchar(args[cur_arg + 1]);
2074 if (err) {
2075 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2076 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002077 err_code |= ERR_ALERT | ERR_FATAL;
2078 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002079 }
2080
Willy Tarreau68a897b2009-12-03 23:28:34 +01002081 if (!curproxy->cookie_domain) {
2082 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2083 } else {
2084 /* one domain was already specified, add another one by
2085 * building the string which will be returned along with
2086 * the cookie.
2087 */
2088 char *new_ptr;
2089 int new_len = strlen(curproxy->cookie_domain) +
2090 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2091 new_ptr = malloc(new_len);
2092 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2093 free(curproxy->cookie_domain);
2094 curproxy->cookie_domain = new_ptr;
2095 }
Willy Tarreau31936852010-10-06 16:59:56 +02002096 cur_arg++;
2097 }
2098 else if (!strcmp(args[cur_arg], "maxidle")) {
2099 unsigned int maxidle;
2100 const char *res;
2101
2102 if (!*args[cur_arg + 1]) {
2103 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2104 file, linenum, args[cur_arg]);
2105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
2107 }
2108
2109 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2110 if (res) {
2111 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2112 file, linenum, *res, args[cur_arg]);
2113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
2115 }
2116 curproxy->cookie_maxidle = maxidle;
2117 cur_arg++;
2118 }
2119 else if (!strcmp(args[cur_arg], "maxlife")) {
2120 unsigned int maxlife;
2121 const char *res;
2122
2123 if (!*args[cur_arg + 1]) {
2124 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2125 file, linenum, args[cur_arg]);
2126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
2129
2130 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2131 if (res) {
2132 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2133 file, linenum, *res, args[cur_arg]);
2134 err_code |= ERR_ALERT | ERR_FATAL;
2135 goto out;
2136 }
2137 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002138 cur_arg++;
2139 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002141 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 +02002142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
2146 cur_arg++;
2147 }
Willy Tarreau67402132012-05-31 20:40:20 +02002148 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2150 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002151 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 }
2153
Willy Tarreau67402132012-05-31 20:40:20 +02002154 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2156 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002157 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002159
Willy Tarreau67402132012-05-31 20:40:20 +02002160 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002161 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2162 file, linenum);
2163 err_code |= ERR_ALERT | ERR_FATAL;
2164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002166 else if (!strcmp(args[0], "persist")) { /* persist */
2167 if (*(args[1]) == 0) {
2168 Alert("parsing [%s:%d] : missing persist method.\n",
2169 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002172 }
2173
2174 if (!strncmp(args[1], "rdp-cookie", 10)) {
2175 curproxy->options2 |= PR_O2_RDPC_PRST;
2176
Emeric Brunb982a3d2010-01-04 15:45:53 +01002177 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002178 const char *beg, *end;
2179
2180 beg = args[1] + 11;
2181 end = strchr(beg, ')');
2182
2183 if (!end || end == beg) {
2184 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2185 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002188 }
2189
2190 free(curproxy->rdp_cookie_name);
2191 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2192 curproxy->rdp_cookie_len = end-beg;
2193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002194 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002195 free(curproxy->rdp_cookie_name);
2196 curproxy->rdp_cookie_name = strdup("msts");
2197 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2198 }
2199 else { /* syntax */
2200 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002204 }
2205 }
2206 else {
2207 Alert("parsing [%s:%d] : unknown persist method.\n",
2208 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
2210 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002211 }
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002214 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002216 if (curproxy == &defproxy) {
2217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
2221
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002226 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 }
2231 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002232 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 curproxy->appsession_name = strdup(args[1]);
2234 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2235 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002236 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2237 if (err) {
2238 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2239 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002242 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002243 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002244
Willy Tarreau51041c72007-09-09 21:56:53 +02002245 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2246 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002247 err_code |= ERR_ALERT | ERR_ABORT;
2248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002250
2251 cur_arg = 6;
2252 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002253 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2254 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002255 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002256 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002257 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002258 } else if (!strcmp(args[cur_arg], "prefix")) {
2259 curproxy->options2 |= PR_O2_AS_PFX;
2260 } else if (!strcmp(args[cur_arg], "mode")) {
2261 if (!*args[cur_arg + 1]) {
2262 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2263 file, linenum, args[0], args[cur_arg]);
2264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
2266 }
2267
2268 cur_arg++;
2269 if (!strcmp(args[cur_arg], "query-string")) {
2270 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2271 curproxy->options2 |= PR_O2_AS_M_QS;
2272 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2273 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2274 curproxy->options2 |= PR_O2_AS_M_PP;
2275 } else {
2276 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002281 cur_arg++;
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 } /* Url App Session */
2284 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002285 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002287
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (*(args[4]) == 0) {
2296 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2297 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002301 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 curproxy->capture_name = strdup(args[2]);
2303 curproxy->capture_namelen = strlen(curproxy->capture_name);
2304 curproxy->capture_len = atol(args[4]);
2305 if (curproxy->capture_len >= CAPTURE_LEN) {
2306 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2307 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002308 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 curproxy->capture_len = CAPTURE_LEN - 1;
2310 }
2311 curproxy->to_log |= LW_COOKIE;
2312 }
2313 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2314 struct cap_hdr *hdr;
2315
2316 if (curproxy == &defproxy) {
2317 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 +02002318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 }
2321
2322 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2323 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2324 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 }
2328
2329 hdr = calloc(sizeof(struct cap_hdr), 1);
2330 hdr->next = curproxy->req_cap;
2331 hdr->name = strdup(args[3]);
2332 hdr->namelen = strlen(args[3]);
2333 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002334 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 hdr->index = curproxy->nb_req_cap++;
2336 curproxy->req_cap = hdr;
2337 curproxy->to_log |= LW_REQHDR;
2338 }
2339 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2340 struct cap_hdr *hdr;
2341
2342 if (curproxy == &defproxy) {
2343 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 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
2347
2348 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2349 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2350 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 hdr = calloc(sizeof(struct cap_hdr), 1);
2355 hdr->next = curproxy->rsp_cap;
2356 hdr->name = strdup(args[3]);
2357 hdr->namelen = strlen(args[3]);
2358 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002359 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 hdr->index = curproxy->nb_rsp_cap++;
2361 curproxy->rsp_cap = hdr;
2362 curproxy->to_log |= LW_RSPHDR;
2363 }
2364 else {
2365 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
2370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002372 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 if (*(args[1]) == 0) {
2376 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2377 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
2379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 curproxy->conn_retries = atol(args[1]);
2382 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002383 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002384 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002385
2386 if (curproxy == &defproxy) {
2387 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391
Willy Tarreauff011f22011-01-06 17:51:27 +01002392 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002393 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2394 file, linenum, args[0]);
2395 err_code |= ERR_WARN;
2396 }
2397
Willy Tarreauff011f22011-01-06 17:51:27 +01002398 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002399
Willy Tarreauff011f22011-01-06 17:51:27 +01002400 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002401 err_code |= ERR_ALERT | ERR_ABORT;
2402 goto out;
2403 }
2404
Willy Tarreauff011f22011-01-06 17:51:27 +01002405 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2406 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002407 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002408 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2409 /* set the header name and length into the proxy structure */
2410 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2411 err_code |= ERR_WARN;
2412
2413 if (!*args[1]) {
2414 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2415 file, linenum, args[0]);
2416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
2418 }
2419
2420 /* set the desired header name */
2421 free(curproxy->server_id_hdr_name);
2422 curproxy->server_id_hdr_name = strdup(args[1]);
2423 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2424 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002425 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002426 if (curproxy == &defproxy) {
2427 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002430 }
2431
Willy Tarreauef6494c2010-01-28 17:12:36 +01002432 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002433 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2434 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002437 }
2438
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002439 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2440 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2441 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002444 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002445
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002446 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002447 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002448 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002449 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002450 struct redirect_rule *rule;
2451 int cur_arg;
2452 int type = REDIRECT_TYPE_NONE;
2453 int code = 302;
2454 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002455 char *cookie = NULL;
2456 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002457 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002458
Cyril Bonté99ed3272010-01-24 23:29:44 +01002459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002465 cur_arg = 1;
2466 while (*(args[cur_arg])) {
2467 if (!strcmp(args[cur_arg], "location")) {
2468 if (!*args[cur_arg + 1]) {
2469 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2470 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002473 }
2474
2475 type = REDIRECT_TYPE_LOCATION;
2476 cur_arg++;
2477 destination = args[cur_arg];
2478 }
2479 else if (!strcmp(args[cur_arg], "prefix")) {
2480 if (!*args[cur_arg + 1]) {
2481 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2482 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002485 }
2486
2487 type = REDIRECT_TYPE_PREFIX;
2488 cur_arg++;
2489 destination = args[cur_arg];
2490 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002491 else if (!strcmp(args[cur_arg], "scheme")) {
2492 if (!*args[cur_arg + 1]) {
2493 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2494 file, linenum, args[0], args[cur_arg]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
2499 type = REDIRECT_TYPE_SCHEME;
2500 cur_arg++;
2501 destination = args[cur_arg];
2502 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002503 else if (!strcmp(args[cur_arg], "set-cookie")) {
2504 if (!*args[cur_arg + 1]) {
2505 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2506 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002509 }
2510
2511 cur_arg++;
2512 cookie = args[cur_arg];
2513 cookie_set = 1;
2514 }
2515 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2516 if (!*args[cur_arg + 1]) {
2517 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2518 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002521 }
2522
2523 cur_arg++;
2524 cookie = args[cur_arg];
2525 cookie_set = 0;
2526 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002527 else if (!strcmp(args[cur_arg],"code")) {
2528 if (!*args[cur_arg + 1]) {
2529 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 }
2534 cur_arg++;
2535 code = atol(args[cur_arg]);
2536 if (code < 301 || code > 303) {
2537 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2538 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002541 }
2542 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002543 else if (!strcmp(args[cur_arg],"drop-query")) {
2544 flags |= REDIRECT_FLAG_DROP_QS;
2545 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002546 else if (!strcmp(args[cur_arg],"append-slash")) {
2547 flags |= REDIRECT_FLAG_APPEND_SLASH;
2548 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002549 else if (strcmp(args[cur_arg], "if") == 0 ||
2550 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002551 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002552 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002553 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2554 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
2557 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002558 break;
2559 }
2560 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002561 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 }
2566 cur_arg++;
2567 }
2568
2569 if (type == REDIRECT_TYPE_NONE) {
2570 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2571 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002574 }
2575
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002576 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2577 rule->cond = cond;
2578 rule->rdr_str = strdup(destination);
2579 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002580 if (cookie) {
2581 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002582 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002583 */
2584 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002585 if (cookie_set) {
2586 rule->cookie_str = malloc(rule->cookie_len + 10);
2587 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2588 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2589 rule->cookie_len += 9;
2590 } else {
2591 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002592 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002593 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2594 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002595 }
2596 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002597 rule->type = type;
2598 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002599 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 LIST_INIT(&rule->list);
2601 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002602 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2603 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002604 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002605 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002606 struct switching_rule *rule;
2607
Willy Tarreaub099aca2008-10-12 17:26:37 +02002608 if (curproxy == &defproxy) {
2609 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002612 }
2613
Willy Tarreau55ea7572007-06-17 19:56:27 +02002614 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002616
2617 if (*(args[1]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002621 }
2622
Willy Tarreauef6494c2010-01-28 17:12:36 +01002623 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002624 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 }
2629
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002630 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2631 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2632 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_ALERT | ERR_FATAL;
2634 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002635 }
2636
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002637 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002638
Willy Tarreau55ea7572007-06-17 19:56:27 +02002639 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2640 rule->cond = cond;
2641 rule->be.name = strdup(args[1]);
2642 LIST_INIT(&rule->list);
2643 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2644 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002645 else if (strcmp(args[0], "use-server") == 0) {
2646 struct server_rule *rule;
2647
2648 if (curproxy == &defproxy) {
2649 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
2654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2655 err_code |= ERR_WARN;
2656
2657 if (*(args[1]) == 0) {
2658 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
2662
2663 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2664 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2665 file, linenum, args[0]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002670 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2671 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2672 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2678
2679 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2680 rule->cond = cond;
2681 rule->srv.name = strdup(args[1]);
2682 LIST_INIT(&rule->list);
2683 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2684 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2685 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002686 else if ((!strcmp(args[0], "force-persist")) ||
2687 (!strcmp(args[0], "ignore-persist"))) {
2688 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002689
2690 if (curproxy == &defproxy) {
2691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695
2696 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2697 err_code |= ERR_WARN;
2698
Willy Tarreauef6494c2010-01-28 17:12:36 +01002699 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002700 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2701 file, linenum, args[0]);
2702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
2704 }
2705
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002706 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2707 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2708 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
2711 }
2712
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002713 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002714
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002715 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002716 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002717 if (!strcmp(args[0], "force-persist")) {
2718 rule->type = PERSIST_TYPE_FORCE;
2719 } else {
2720 rule->type = PERSIST_TYPE_IGNORE;
2721 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002722 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002723 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002724 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002725 else if (!strcmp(args[0], "stick-table")) {
2726 int myidx = 1;
2727
Emeric Brun32da3c42010-09-23 18:39:19 +02002728 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 curproxy->table.type = (unsigned int)-1;
2730 while (*args[myidx]) {
2731 const char *err;
2732
2733 if (strcmp(args[myidx], "size") == 0) {
2734 myidx++;
2735 if (!*(args[myidx])) {
2736 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2737 file, linenum, args[myidx-1]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2742 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2743 file, linenum, *err, args[myidx-1]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002747 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002748 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002749 else if (strcmp(args[myidx], "peers") == 0) {
2750 myidx++;
2751 if (!*(args[myidx])) {
2752 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2753 file, linenum, args[myidx-1]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757 curproxy->table.peers.name = strdup(args[myidx++]);
2758 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 else if (strcmp(args[myidx], "expire") == 0) {
2760 myidx++;
2761 if (!*(args[myidx])) {
2762 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2763 file, linenum, args[myidx-1]);
2764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
2766 }
2767 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2768 if (err) {
2769 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2770 file, linenum, *err, args[myidx-1]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002775 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002776 }
2777 else if (strcmp(args[myidx], "nopurge") == 0) {
2778 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002779 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002780 }
2781 else if (strcmp(args[myidx], "type") == 0) {
2782 myidx++;
2783 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2784 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2785 file, linenum, args[myidx]);
2786 err_code |= ERR_ALERT | ERR_FATAL;
2787 goto out;
2788 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002789 /* myidx already points to next arg */
2790 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002791 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002792 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002793 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002794
2795 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002796 nw = args[myidx];
2797 while (*nw) {
2798 /* the "store" keyword supports a comma-separated list */
2799 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002800 sa = NULL; /* store arg */
2801 while (*nw && *nw != ',') {
2802 if (*nw == '(') {
2803 *nw = 0;
2804 sa = ++nw;
2805 while (*nw != ')') {
2806 if (!*nw) {
2807 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2808 file, linenum, args[0], cw);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812 nw++;
2813 }
2814 *nw = '\0';
2815 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002816 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002817 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002818 if (*nw)
2819 *nw++ = '\0';
2820 type = stktable_get_data_type(cw);
2821 if (type < 0) {
2822 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2823 file, linenum, args[0], cw);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
Willy Tarreauac782882010-06-20 10:41:54 +02002827
2828 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2829 switch (err) {
2830 case PE_NONE: break;
2831 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002832 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2833 file, linenum, args[0], cw);
2834 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002835 break;
2836
2837 case PE_ARG_MISSING:
2838 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2839 file, linenum, args[0], cw);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842
2843 case PE_ARG_NOT_USED:
2844 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2845 file, linenum, args[0], cw);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848
2849 default:
2850 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2851 file, linenum, args[0], cw);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002854 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002855 }
2856 myidx++;
2857 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002858 else {
2859 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2860 file, linenum, args[myidx]);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002864 }
2865
2866 if (!curproxy->table.size) {
2867 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2868 file, linenum);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872
2873 if (curproxy->table.type == (unsigned int)-1) {
2874 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2875 file, linenum);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879 }
2880 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002881 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002882 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002883 int myidx = 0;
2884 const char *name = NULL;
2885 int flags;
2886
2887 if (curproxy == &defproxy) {
2888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
2891 }
2892
2893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2894 err_code |= ERR_WARN;
2895 goto out;
2896 }
2897
2898 myidx++;
2899 if ((strcmp(args[myidx], "store") == 0) ||
2900 (strcmp(args[myidx], "store-request") == 0)) {
2901 myidx++;
2902 flags = STK_IS_STORE;
2903 }
2904 else if (strcmp(args[myidx], "store-response") == 0) {
2905 myidx++;
2906 flags = STK_IS_STORE | STK_ON_RSP;
2907 }
2908 else if (strcmp(args[myidx], "match") == 0) {
2909 myidx++;
2910 flags = STK_IS_MATCH;
2911 }
2912 else if (strcmp(args[myidx], "on") == 0) {
2913 myidx++;
2914 flags = STK_IS_MATCH | STK_IS_STORE;
2915 }
2916 else {
2917 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921
2922 if (*(args[myidx]) == 0) {
2923 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002928 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002929 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002930 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934
2935 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002936 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2938 file, linenum, args[0], expr->fetch->kw);
2939 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002940 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 goto out;
2942 }
2943 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002944 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2946 file, linenum, args[0], expr->fetch->kw);
2947 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002948 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 goto out;
2950 }
2951 }
2952
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02002953 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
2954 if (expr->fetch->cap & SMP_CAP_L7)
2955 curproxy->acl_requires |= ACL_USE_L7_ANY;
2956
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 if (strcmp(args[myidx], "table") == 0) {
2958 myidx++;
2959 name = args[myidx++];
2960 }
2961
Willy Tarreauef6494c2010-01-28 17:12:36 +01002962 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002963 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2964 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2965 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002967 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002968 goto out;
2969 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002970 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002971 else if (*(args[myidx])) {
2972 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2973 file, linenum, args[0], args[myidx]);
2974 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002975 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002976 goto out;
2977 }
Emeric Brun97679e72010-09-23 17:56:44 +02002978 if (flags & STK_ON_RSP)
2979 err_code |= warnif_cond_requires_req(cond, file, linenum);
2980 else
2981 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002982
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2984 rule->cond = cond;
2985 rule->expr = expr;
2986 rule->flags = flags;
2987 rule->table.name = name ? strdup(name) : NULL;
2988 LIST_INIT(&rule->list);
2989 if (flags & STK_ON_RSP)
2990 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2991 else
2992 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002995 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002997
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2999 curproxy->uri_auth = NULL; /* we must detach from the default config */
3000
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003001 if (!*args[1]) {
3002 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003003 } else if (!strcmp(args[1], "admin")) {
3004 struct stats_admin_rule *rule;
3005
3006 if (curproxy == &defproxy) {
3007 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011
3012 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3013 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3014 err_code |= ERR_ALERT | ERR_ABORT;
3015 goto out;
3016 }
3017
3018 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3019 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3020 file, linenum, args[0], args[1]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003024 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3025 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3026 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
3031 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3032
3033 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3034 rule->cond = cond;
3035 LIST_INIT(&rule->list);
3036 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 } else if (!strcmp(args[1], "uri")) {
3038 if (*(args[2]) == 0) {
3039 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3043 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_ABORT;
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 }
3047 } else if (!strcmp(args[1], "realm")) {
3048 if (*(args[2]) == 0) {
3049 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003057 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003058 unsigned interval;
3059
3060 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3061 if (err) {
3062 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3063 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003066 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3067 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_ABORT;
3069 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003070 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003071 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003072 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003073
3074 if (curproxy == &defproxy) {
3075 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
3078 }
3079
3080 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3081 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
3084 }
3085
Willy Tarreauff011f22011-01-06 17:51:27 +01003086 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3087 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003088 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3089 file, linenum, args[0]);
3090 err_code |= ERR_WARN;
3091 }
3092
Willy Tarreauff011f22011-01-06 17:51:27 +01003093 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003094
Willy Tarreauff011f22011-01-06 17:51:27 +01003095 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
3098 }
3099
Willy Tarreauff011f22011-01-06 17:51:27 +01003100 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3101 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003102
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 } else if (!strcmp(args[1], "auth")) {
3104 if (*(args[2]) == 0) {
3105 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_ABORT;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 }
3113 } else if (!strcmp(args[1], "scope")) {
3114 if (*(args[2]) == 0) {
3115 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3119 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_ABORT;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 }
3123 } else if (!strcmp(args[1], "enable")) {
3124 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3125 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003126 err_code |= ERR_ALERT | ERR_ABORT;
3127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003129 } else if (!strcmp(args[1], "hide-version")) {
3130 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_ABORT;
3133 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003134 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003135 } else if (!strcmp(args[1], "show-legends")) {
3136 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3137 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3138 err_code |= ERR_ALERT | ERR_ABORT;
3139 goto out;
3140 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003141 } else if (!strcmp(args[1], "show-node")) {
3142
3143 if (*args[2]) {
3144 int i;
3145 char c;
3146
3147 for (i=0; args[2][i]; i++) {
3148 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003149 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3150 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003151 break;
3152 }
3153
3154 if (!i || args[2][i]) {
3155 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3156 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3157 file, linenum, args[0], args[1]);
3158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
3160 }
3161 }
3162
3163 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3165 err_code |= ERR_ALERT | ERR_ABORT;
3166 goto out;
3167 }
3168 } else if (!strcmp(args[1], "show-desc")) {
3169 char *desc = NULL;
3170
3171 if (*args[2]) {
3172 int i, len=0;
3173 char *d;
3174
3175 for(i=2; *args[i]; i++)
3176 len += strlen(args[i])+1;
3177
3178 desc = d = (char *)calloc(1, len);
3179
3180 d += sprintf(d, "%s", args[2]);
3181 for(i=3; *args[i]; i++)
3182 d += sprintf(d, " %s", args[i]);
3183 }
3184
3185 if (!*args[2] && !global.desc)
3186 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3187 file, linenum, args[1]);
3188 else {
3189 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3190 free(desc);
3191 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3192 err_code |= ERR_ALERT | ERR_ABORT;
3193 goto out;
3194 }
3195 free(desc);
3196 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003198stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003199 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 +01003200 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 }
3204 }
3205 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003206 int optnum;
3207
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003208 if (*(args[1]) == '\0') {
3209 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3210 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003214
3215 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3216 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003217 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3218 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3219 file, linenum, cfg_opts[optnum].name);
3220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
3222 }
Willy Tarreau93893792009-07-23 13:19:11 +02003223 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3224 err_code |= ERR_WARN;
3225 goto out;
3226 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003227
Willy Tarreau3842f002009-06-14 11:39:52 +02003228 curproxy->no_options &= ~cfg_opts[optnum].val;
3229 curproxy->options &= ~cfg_opts[optnum].val;
3230
3231 switch (kwm) {
3232 case KWM_STD:
3233 curproxy->options |= cfg_opts[optnum].val;
3234 break;
3235 case KWM_NO:
3236 curproxy->no_options |= cfg_opts[optnum].val;
3237 break;
3238 case KWM_DEF: /* already cleared */
3239 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003240 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003241
Willy Tarreau93893792009-07-23 13:19:11 +02003242 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003243 }
3244 }
3245
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003246 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3247 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003248 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3249 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3250 file, linenum, cfg_opts2[optnum].name);
3251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
Willy Tarreau93893792009-07-23 13:19:11 +02003254 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3255 err_code |= ERR_WARN;
3256 goto out;
3257 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003258
Willy Tarreau3842f002009-06-14 11:39:52 +02003259 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3260 curproxy->options2 &= ~cfg_opts2[optnum].val;
3261
3262 switch (kwm) {
3263 case KWM_STD:
3264 curproxy->options2 |= cfg_opts2[optnum].val;
3265 break;
3266 case KWM_NO:
3267 curproxy->no_options2 |= cfg_opts2[optnum].val;
3268 break;
3269 case KWM_DEF: /* already cleared */
3270 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003271 }
Willy Tarreau93893792009-07-23 13:19:11 +02003272 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003273 }
3274 }
3275
Willy Tarreau3842f002009-06-14 11:39:52 +02003276 if (kwm != KWM_STD) {
3277 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003278 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003281 }
3282
Emeric Brun3a058f32009-06-30 18:26:00 +02003283 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003284 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003286 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003287 if (*(args[2]) != '\0') {
3288 if (!strcmp(args[2], "clf")) {
3289 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003290 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003291 } else {
3292 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003295 }
3296 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003297 if (curproxy->logformat_string != default_http_log_format &&
3298 curproxy->logformat_string != default_tcp_log_format &&
3299 curproxy->logformat_string != clf_http_log_format)
3300 free(curproxy->logformat_string);
3301 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003302 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003303 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003305 if (curproxy->logformat_string != default_http_log_format &&
3306 curproxy->logformat_string != default_tcp_log_format &&
3307 curproxy->logformat_string != clf_http_log_format)
3308 free(curproxy->logformat_string);
3309 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 else if (!strcmp(args[1], "tcpka")) {
3312 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003313 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003314 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003315
3316 if (curproxy->cap & PR_CAP_FE)
3317 curproxy->options |= PR_O_TCP_CLI_KA;
3318 if (curproxy->cap & PR_CAP_BE)
3319 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003320 }
3321 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_WARN;
3324
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003326 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003327 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003328 curproxy->options2 &= ~PR_O2_CHK_ANY;
3329 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 if (!*args[2]) { /* no argument */
3331 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3332 curproxy->check_len = strlen(DEF_CHECK_REQ);
3333 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003334 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 curproxy->check_req = (char *)malloc(reqlen);
3336 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003337 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003339 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 if (*args[4])
3341 reqlen += strlen(args[4]);
3342 else
3343 reqlen += strlen("HTTP/1.0");
3344
3345 curproxy->check_req = (char *)malloc(reqlen);
3346 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003347 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003349 }
3350 else if (!strcmp(args[1], "ssl-hello-chk")) {
3351 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003352 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003354
Willy Tarreaua534fea2008-08-03 12:19:50 +02003355 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003356 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003357 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003358 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
Willy Tarreau23677902007-05-08 23:50:35 +02003360 else if (!strcmp(args[1], "smtpchk")) {
3361 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003362 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003363 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003364 curproxy->options2 &= ~PR_O2_CHK_ANY;
3365 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003366
3367 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3368 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3369 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3370 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3371 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3372 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3373 curproxy->check_req = (char *)malloc(reqlen);
3374 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3375 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3376 } else {
3377 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3378 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3379 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3380 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3381 }
3382 }
3383 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003384 else if (!strcmp(args[1], "pgsql-check")) {
3385 /* use PostgreSQL request to check servers' health */
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3387 err_code |= ERR_WARN;
3388
3389 free(curproxy->check_req);
3390 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003391 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003392 curproxy->options2 |= PR_O2_PGSQL_CHK;
3393
3394 if (*(args[2])) {
3395 int cur_arg = 2;
3396
3397 while (*(args[cur_arg])) {
3398 if (strcmp(args[cur_arg], "user") == 0) {
3399 char * packet;
3400 uint32_t packet_len;
3401 uint32_t pv;
3402
3403 /* suboption header - needs additional argument for it */
3404 if (*(args[cur_arg+1]) == 0) {
3405 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3406 file, linenum, args[0], args[1], args[cur_arg]);
3407 err_code |= ERR_ALERT | ERR_FATAL;
3408 goto out;
3409 }
3410
3411 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3412 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3413 pv = htonl(0x30000); /* protocol version 3.0 */
3414
3415 packet = (char*) calloc(1, packet_len);
3416
3417 memcpy(packet + 4, &pv, 4);
3418
3419 /* copy "user" */
3420 memcpy(packet + 8, "user", 4);
3421
3422 /* copy username */
3423 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3424
3425 free(curproxy->check_req);
3426 curproxy->check_req = packet;
3427 curproxy->check_len = packet_len;
3428
3429 packet_len = htonl(packet_len);
3430 memcpy(packet, &packet_len, 4);
3431 cur_arg += 2;
3432 } else {
3433 /* unknown suboption - catchall */
3434 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3435 file, linenum, args[0], args[1]);
3436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439 } /* end while loop */
3440 }
3441 }
3442
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003443 else if (!strcmp(args[1], "redis-check")) {
3444 /* use REDIS PING request to check servers' health */
3445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3446 err_code |= ERR_WARN;
3447
3448 free(curproxy->check_req);
3449 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003450 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003451 curproxy->options2 |= PR_O2_REDIS_CHK;
3452
3453 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3454 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3455 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3456 }
3457
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003458 else if (!strcmp(args[1], "mysql-check")) {
3459 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003460 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3461 err_code |= ERR_WARN;
3462
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003463 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003464 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003465 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003466 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003467
3468 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3469 * const char mysql40_client_auth_pkt[] = {
3470 * "\x0e\x00\x00" // packet length
3471 * "\x01" // packet number
3472 * "\x00\x00" // client capabilities
3473 * "\x00\x00\x01" // max packet
3474 * "haproxy\x00" // username (null terminated string)
3475 * "\x00" // filler (always 0x00)
3476 * "\x01\x00\x00" // packet length
3477 * "\x00" // packet number
3478 * "\x01" // COM_QUIT command
3479 * };
3480 */
3481
3482 if (*(args[2])) {
3483 int cur_arg = 2;
3484
3485 while (*(args[cur_arg])) {
3486 if (strcmp(args[cur_arg], "user") == 0) {
3487 char *mysqluser;
3488 int packetlen, reqlen, userlen;
3489
3490 /* suboption header - needs additional argument for it */
3491 if (*(args[cur_arg+1]) == 0) {
3492 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3493 file, linenum, args[0], args[1], args[cur_arg]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497 mysqluser = args[cur_arg + 1];
3498 userlen = strlen(mysqluser);
3499 packetlen = userlen + 7;
3500 reqlen = packetlen + 9;
3501
3502 free(curproxy->check_req);
3503 curproxy->check_req = (char *)calloc(1, reqlen);
3504 curproxy->check_len = reqlen;
3505
3506 snprintf(curproxy->check_req, 4, "%c%c%c",
3507 ((unsigned char) packetlen & 0xff),
3508 ((unsigned char) (packetlen >> 8) & 0xff),
3509 ((unsigned char) (packetlen >> 16) & 0xff));
3510
3511 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003512 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003513 curproxy->check_req[8] = 1;
3514 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3515 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3516 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3517 cur_arg += 2;
3518 } else {
3519 /* unknown suboption - catchall */
3520 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3521 file, linenum, args[0], args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 } /* end while loop */
3526 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003527 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003528 else if (!strcmp(args[1], "ldap-check")) {
3529 /* use LDAP request to check servers' health */
3530 free(curproxy->check_req);
3531 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003532 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003533 curproxy->options2 |= PR_O2_LDAP_CHK;
3534
3535 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3536 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3537 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3538 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003539 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003540 int cur_arg;
3541
3542 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3543 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003544 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003545
Willy Tarreau87cf5142011-08-19 22:57:24 +02003546 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003547
3548 free(curproxy->fwdfor_hdr_name);
3549 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3550 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3551
3552 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3553 cur_arg = 2;
3554 while (*(args[cur_arg])) {
3555 if (!strcmp(args[cur_arg], "except")) {
3556 /* suboption except - needs additional argument for it */
3557 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3558 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3559 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003562 }
3563 /* flush useless bits */
3564 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003565 cur_arg += 2;
3566 } else if (!strcmp(args[cur_arg], "header")) {
3567 /* suboption header - needs additional argument for it */
3568 if (*(args[cur_arg+1]) == 0) {
3569 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3570 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003573 }
3574 free(curproxy->fwdfor_hdr_name);
3575 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3576 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3577 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003578 } else if (!strcmp(args[cur_arg], "if-none")) {
3579 curproxy->options &= ~PR_O_FF_ALWAYS;
3580 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003581 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003582 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003583 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003584 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003587 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003588 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003589 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003590 else if (!strcmp(args[1], "originalto")) {
3591 int cur_arg;
3592
3593 /* insert x-original-to field, but not for the IP address listed as an except.
3594 * set default options (ie: bitfield, header name, etc)
3595 */
3596
3597 curproxy->options |= PR_O_ORGTO;
3598
3599 free(curproxy->orgto_hdr_name);
3600 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3601 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3602
Willy Tarreau87cf5142011-08-19 22:57:24 +02003603 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003604 cur_arg = 2;
3605 while (*(args[cur_arg])) {
3606 if (!strcmp(args[cur_arg], "except")) {
3607 /* suboption except - needs additional argument for it */
3608 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3609 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3610 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003613 }
3614 /* flush useless bits */
3615 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3616 cur_arg += 2;
3617 } else if (!strcmp(args[cur_arg], "header")) {
3618 /* suboption header - needs additional argument for it */
3619 if (*(args[cur_arg+1]) == 0) {
3620 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3621 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003624 }
3625 free(curproxy->orgto_hdr_name);
3626 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3627 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3628 cur_arg += 2;
3629 } else {
3630 /* unknown suboption - catchall */
3631 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3632 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003635 }
3636 } /* end while loop */
3637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 else {
3639 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
Willy Tarreau93893792009-07-23 13:19:11 +02003643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003645 else if (!strcmp(args[0], "default_backend")) {
3646 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003648
3649 if (*(args[1]) == 0) {
3650 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003653 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003654 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003655 curproxy->defbe.name = strdup(args[1]);
3656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003660
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003661 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3662 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 /* enable reconnections to dispatch */
3665 curproxy->options |= PR_O_REDISP;
3666 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003667 else if (!strcmp(args[0], "http-check")) {
3668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003670
3671 if (strcmp(args[1], "disable-on-404") == 0) {
3672 /* enable a graceful server shutdown on an HTTP 404 response */
3673 curproxy->options |= PR_O_DISABLE404;
3674 }
Willy Tarreauef781042010-01-27 11:53:01 +01003675 else if (strcmp(args[1], "send-state") == 0) {
3676 /* enable emission of the apparent state of a server in HTTP checks */
3677 curproxy->options2 |= PR_O2_CHK_SNDST;
3678 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003679 else if (strcmp(args[1], "expect") == 0) {
3680 const char *ptr_arg;
3681 int cur_arg;
3682
3683 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3684 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688
3689 cur_arg = 2;
3690 /* consider exclamation marks, sole or at the beginning of a word */
3691 while (*(ptr_arg = args[cur_arg])) {
3692 while (*ptr_arg == '!') {
3693 curproxy->options2 ^= PR_O2_EXP_INV;
3694 ptr_arg++;
3695 }
3696 if (*ptr_arg)
3697 break;
3698 cur_arg++;
3699 }
3700 /* now ptr_arg points to the beginning of a word past any possible
3701 * exclamation mark, and cur_arg is the argument which holds this word.
3702 */
3703 if (strcmp(ptr_arg, "status") == 0) {
3704 if (!*(args[cur_arg + 1])) {
3705 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3706 file, linenum, args[0], args[1], ptr_arg);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003711 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003712 curproxy->expect_str = strdup(args[cur_arg + 1]);
3713 }
3714 else if (strcmp(ptr_arg, "string") == 0) {
3715 if (!*(args[cur_arg + 1])) {
3716 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3717 file, linenum, args[0], args[1], ptr_arg);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003722 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003723 curproxy->expect_str = strdup(args[cur_arg + 1]);
3724 }
3725 else if (strcmp(ptr_arg, "rstatus") == 0) {
3726 if (!*(args[cur_arg + 1])) {
3727 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3728 file, linenum, args[0], args[1], ptr_arg);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003733 free(curproxy->expect_str);
3734 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3735 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003736 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3737 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3738 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3739 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743 }
3744 else if (strcmp(ptr_arg, "rstring") == 0) {
3745 if (!*(args[cur_arg + 1])) {
3746 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3747 file, linenum, args[0], args[1], ptr_arg);
3748 err_code |= ERR_ALERT | ERR_FATAL;
3749 goto out;
3750 }
3751 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003752 free(curproxy->expect_str);
3753 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3754 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003755 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3756 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3757 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3758 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762 }
3763 else {
3764 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3765 file, linenum, args[0], args[1], ptr_arg);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003770 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003771 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 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003774 }
3775 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003776 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003777 if (curproxy == &defproxy) {
3778 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003781 }
3782
Willy Tarreaub80c2302007-11-30 20:51:32 +01003783 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003785
3786 if (strcmp(args[1], "fail") == 0) {
3787 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003788 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003789 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3790 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003793 }
3794
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003795 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3796 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3797 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003800 }
3801 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3802 }
3803 else {
3804 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003807 }
3808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809#ifdef TPROXY
3810 else if (!strcmp(args[0], "transparent")) {
3811 /* enable transparent proxy connections */
3812 curproxy->options |= PR_O_TRANSP;
3813 }
3814#endif
3815 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 if (*(args[1]) == 0) {
3820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
3824 curproxy->maxconn = atol(args[1]);
3825 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003826 else if (!strcmp(args[0], "backlog")) { /* backlog */
3827 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003829
3830 if (*(args[1]) == 0) {
3831 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003834 }
3835 curproxy->backlog = atol(args[1]);
3836 }
Willy Tarreau86034312006-12-29 00:10:33 +01003837 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003838 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003840
Willy Tarreau86034312006-12-29 00:10:33 +01003841 if (*(args[1]) == 0) {
3842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003845 }
3846 curproxy->fullconn = atol(args[1]);
3847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3849 if (*(args[1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003854 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3855 if (err) {
3856 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3857 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003860 }
3861 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
3863 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003864 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 if (curproxy == &defproxy) {
3866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003870 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003872
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 if (strchr(args[1], ':') == NULL) {
3874 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003878 sk = str2sa(args[1]);
3879 if (!sk) {
3880 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003885 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
3887 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003888 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003890
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003891 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3892 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003897 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3899 err_code |= ERR_WARN;
3900
3901 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3902 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3903 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3904 }
3905 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3906 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3907 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3908 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003909 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3910 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3911 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3912 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003913 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003914 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
3917 }
3918 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003919 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003921 char *rport, *raddr;
3922 short realport = 0;
3923 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003925 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003930 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932
3933 if (!*args[2]) {
3934 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3935 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003936 err_code |= ERR_ALERT | ERR_FATAL;
3937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003939
3940 err = invalid_char(args[1]);
3941 if (err) {
3942 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3943 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003946 }
3947
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003949 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003950
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003951 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3952 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3953 err_code |= ERR_ALERT | ERR_ABORT;
3954 goto out;
3955 }
3956
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003957 /* the servers are linked backwards first */
3958 newsrv->next = curproxy->srv;
3959 curproxy->srv = newsrv;
3960 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003961 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003962 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963
Simon Hormanaf514952011-06-21 14:34:57 +09003964 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 LIST_INIT(&newsrv->pendconns);
3966 do_check = 0;
3967 newsrv->state = SRV_RUNNING; /* early server setup */
3968 newsrv->last_change = now.tv_sec;
3969 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003972 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003973 * - IP: => port=+0, relative
3974 * - IP:N => port=N, absolute
3975 * - IP:+N => port=+N, relative
3976 * - IP:-N => port=-N, relative
3977 */
3978 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003979 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 if (rport) {
3981 *rport++ = 0;
3982 realport = atol(rport);
3983 if (!isdigit((unsigned char)*rport))
3984 newsrv->state |= SRV_MAPPORTS;
3985 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003987
Willy Tarreaufab5a432011-03-04 15:31:53 +01003988 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003989 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003990 if (!sk) {
3991 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
3994 }
3995 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02003996 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
3997 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02003998
Willy Tarreau173e7fb2012-09-24 22:47:39 +02003999 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004000 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4001 file, linenum, newsrv->addr.ss_family, args[2]);
4002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
4004 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004005 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004006
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004007 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004008 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004009 newsrv->inter = curproxy->defsrv.inter;
4010 newsrv->fastinter = curproxy->defsrv.fastinter;
4011 newsrv->downinter = curproxy->defsrv.downinter;
4012 newsrv->rise = curproxy->defsrv.rise;
4013 newsrv->fall = curproxy->defsrv.fall;
4014 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4015 newsrv->minconn = curproxy->defsrv.minconn;
4016 newsrv->maxconn = curproxy->defsrv.maxconn;
4017 newsrv->slowstart = curproxy->defsrv.slowstart;
4018 newsrv->onerror = curproxy->defsrv.onerror;
4019 newsrv->consecutive_errors_limit
4020 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004021#ifdef OPENSSL
4022 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4023#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 newsrv->uweight = newsrv->iweight
4025 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 cur_arg = 3;
4030 } else {
4031 newsrv = &curproxy->defsrv;
4032 cur_arg = 1;
4033 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004034
Willy Tarreaubaaee002006-06-26 02:48:02 +02004035 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004036 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 newsrv->cookie = strdup(args[cur_arg + 1]);
4038 newsrv->cklen = strlen(args[cur_arg + 1]);
4039 cur_arg += 2;
4040 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004042 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4043 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4044 cur_arg += 2;
4045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004046 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004047 if (!*args[cur_arg + 1]) {
4048 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4049 file, linenum, args[cur_arg]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
4052 }
4053
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004055 if (newsrv->rise <= 0) {
4056 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4057 file, linenum, args[cur_arg]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
Willy Tarreau96839092010-03-29 10:02:24 +02004062 if (newsrv->health)
4063 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 cur_arg += 2;
4065 }
4066 else if (!strcmp(args[cur_arg], "fall")) {
4067 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004068
4069 if (!*args[cur_arg + 1]) {
4070 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4071 file, linenum, args[cur_arg]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
4076 if (newsrv->fall <= 0) {
4077 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4078 file, linenum, args[cur_arg]);
4079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
4081 }
4082
Willy Tarreaubaaee002006-06-26 02:48:02 +02004083 cur_arg += 2;
4084 }
4085 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004086 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4087 if (err) {
4088 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4089 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004092 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004093 if (val <= 0) {
4094 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4095 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004098 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004099 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004100 cur_arg += 2;
4101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 else if (!strcmp(args[cur_arg], "fastinter")) {
4103 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4104 if (err) {
4105 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4106 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004109 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004110 if (val <= 0) {
4111 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4112 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004115 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004116 newsrv->fastinter = val;
4117 cur_arg += 2;
4118 }
4119 else if (!strcmp(args[cur_arg], "downinter")) {
4120 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4121 if (err) {
4122 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4123 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004126 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004127 if (val <= 0) {
4128 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4129 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004132 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004133 newsrv->downinter = val;
4134 cur_arg += 2;
4135 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004137 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004138 if (!sk) {
4139 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004143 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004144 cur_arg += 2;
4145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004147 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 cur_arg += 2;
4149 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 newsrv->state |= SRV_BACKUP;
4152 cur_arg ++;
4153 }
Simon Hormanfa461682011-06-25 09:39:49 +09004154 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4155 newsrv->state |= SRV_NON_STICK;
4156 cur_arg ++;
4157 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004158 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4159 newsrv->state |= SRV_SEND_PROXY;
4160 cur_arg ++;
4161 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004162 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4163 newsrv->check.send_proxy = 1;
4164 cur_arg ++;
4165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 else if (!strcmp(args[cur_arg], "weight")) {
4167 int w;
4168 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004169 if (w < 0 || w > 256) {
4170 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004175 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 cur_arg += 2;
4177 }
4178 else if (!strcmp(args[cur_arg], "minconn")) {
4179 newsrv->minconn = atol(args[cur_arg + 1]);
4180 cur_arg += 2;
4181 }
4182 else if (!strcmp(args[cur_arg], "maxconn")) {
4183 newsrv->maxconn = atol(args[cur_arg + 1]);
4184 cur_arg += 2;
4185 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004186 else if (!strcmp(args[cur_arg], "maxqueue")) {
4187 newsrv->maxqueue = atol(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004190 else if (!strcmp(args[cur_arg], "slowstart")) {
4191 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004192 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004193 if (err) {
4194 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4195 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004198 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004199 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004200 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4201 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004204 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004205 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004206 cur_arg += 2;
4207 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004208 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004209
4210 if (!*args[cur_arg + 1]) {
4211 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4212 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004215 }
4216
4217 newsrv->trackit = strdup(args[cur_arg + 1]);
4218
4219 cur_arg += 2;
4220 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004221 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 global.maxsock++;
4223 do_check = 1;
4224 cur_arg += 1;
4225 }
Willy Tarreau96839092010-03-29 10:02:24 +02004226 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4227 newsrv->state |= SRV_MAINTAIN;
4228 newsrv->state &= ~SRV_RUNNING;
4229 newsrv->health = 0;
4230 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004231 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004232 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004233 if (!strcmp(args[cur_arg + 1], "none"))
4234 newsrv->observe = HANA_OBS_NONE;
4235 else if (!strcmp(args[cur_arg + 1], "layer4"))
4236 newsrv->observe = HANA_OBS_LAYER4;
4237 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4238 if (curproxy->mode != PR_MODE_HTTP) {
4239 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4240 file, linenum, args[cur_arg + 1]);
4241 err_code |= ERR_ALERT;
4242 }
4243 newsrv->observe = HANA_OBS_LAYER7;
4244 }
4245 else {
4246 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004247 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004248 file, linenum, args[cur_arg], args[cur_arg + 1]);
4249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
4251 }
4252
4253 cur_arg += 2;
4254 }
4255 else if (!strcmp(args[cur_arg], "on-error")) {
4256 if (!strcmp(args[cur_arg + 1], "fastinter"))
4257 newsrv->onerror = HANA_ONERR_FASTINTER;
4258 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4259 newsrv->onerror = HANA_ONERR_FAILCHK;
4260 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4261 newsrv->onerror = HANA_ONERR_SUDDTH;
4262 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4263 newsrv->onerror = HANA_ONERR_MARKDWN;
4264 else {
4265 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004266 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004267 file, linenum, args[cur_arg], args[cur_arg + 1]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271
4272 cur_arg += 2;
4273 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004274 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4275 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4276 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4277 else {
4278 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4279 file, linenum, args[cur_arg], args[cur_arg + 1]);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283
4284 cur_arg += 2;
4285 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004286 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4287 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4288 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4289 else {
4290 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4291 file, linenum, args[cur_arg], args[cur_arg + 1]);
4292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
4295
4296 cur_arg += 2;
4297 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004298 else if (!strcmp(args[cur_arg], "error-limit")) {
4299 if (!*args[cur_arg + 1]) {
4300 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4301 file, linenum, args[cur_arg]);
4302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305
4306 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4307
4308 if (newsrv->consecutive_errors_limit <= 0) {
4309 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4310 file, linenum, args[cur_arg]);
4311 err_code |= ERR_ALERT | ERR_FATAL;
4312 goto out;
4313 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004314 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004315 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004316 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004317 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004318 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004319
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004321#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004322 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004323 file, linenum, "source", "usesrc");
4324#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004325 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004327#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 }
4331 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004332 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4333 if (!sk) {
4334 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
4338 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004339
4340 if (port_low != port_high) {
4341 int i;
4342 if (port_low <= 0 || port_low > 65535 ||
4343 port_high <= 0 || port_high > 65535 ||
4344 port_low > port_high) {
4345 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4346 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004349 }
4350 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4351 for (i = 0; i < newsrv->sport_range->size; i++)
4352 newsrv->sport_range->ports[i] = port_low + i;
4353 }
4354
Willy Tarreaubaaee002006-06-26 02:48:02 +02004355 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004356 while (*(args[cur_arg])) {
4357 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004358#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4359#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004360 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4361 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4362 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004365 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004366#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004367 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004368 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004369 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 }
4373 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004374 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004375 newsrv->state |= SRV_TPROXY_CLI;
4376 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004377 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004378 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004379 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4380 char *name, *end;
4381
4382 name = args[cur_arg+1] + 7;
4383 while (isspace(*name))
4384 name++;
4385
4386 end = name;
4387 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4388 end++;
4389
4390 newsrv->state &= ~SRV_TPROXY_MASK;
4391 newsrv->state |= SRV_TPROXY_DYN;
4392 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4393 newsrv->bind_hdr_len = end - name;
4394 memcpy(newsrv->bind_hdr_name, name, end - name);
4395 newsrv->bind_hdr_name[end-name] = '\0';
4396 newsrv->bind_hdr_occ = -1;
4397
4398 /* now look for an occurrence number */
4399 while (isspace(*end))
4400 end++;
4401 if (*end == ',') {
4402 end++;
4403 name = end;
4404 if (*end == '-')
4405 end++;
4406 while (isdigit(*end))
4407 end++;
4408 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4409 }
4410
4411 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4412 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4413 " occurrences values smaller than %d.\n",
4414 file, linenum, MAX_HDR_HISTORY);
4415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004418 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004419 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004420 if (!sk) {
4421 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004427 }
4428 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004429#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004431#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004432 cur_arg += 2;
4433 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004434#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004436 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004439#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4440 } /* "usesrc" */
4441
4442 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4443#ifdef SO_BINDTODEVICE
4444 if (!*args[cur_arg + 1]) {
4445 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004447 err_code |= ERR_ALERT | ERR_FATAL;
4448 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004449 }
4450 if (newsrv->iface_name)
4451 free(newsrv->iface_name);
4452
4453 newsrv->iface_name = strdup(args[cur_arg + 1]);
4454 newsrv->iface_len = strlen(newsrv->iface_name);
4455 global.last_checks |= LSTCHK_NETADM;
4456#else
4457 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4458 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004461#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004462 cur_arg += 2;
4463 continue;
4464 }
4465 /* this keyword in not an option of "source" */
4466 break;
4467 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004469 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004470 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4471 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004476 static int srv_dumped;
4477 struct srv_kw *kw;
4478 char *err;
4479
4480 kw = srv_find_kw(args[cur_arg]);
4481 if (kw) {
4482 char *err = NULL;
4483 int code;
4484
4485 if (!kw->parse) {
4486 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4487 file, linenum, args[0], args[1], args[cur_arg]);
4488 cur_arg += 1 + kw->skip ;
4489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
4491 }
4492
4493 if (defsrv && !kw->default_ok) {
4494 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4495 file, linenum, args[0], args[1], args[cur_arg]);
4496 cur_arg += 1 + kw->skip ;
4497 err_code |= ERR_ALERT;
4498 continue;
4499 }
4500
4501 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4502 err_code |= code;
4503
4504 if (code) {
4505 if (err && *err) {
4506 indent_msg(&err, 2);
4507 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4508 }
4509 else
4510 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4511 file, linenum, args[0], args[1], args[cur_arg]);
4512 if (code & ERR_FATAL) {
4513 free(err);
4514 cur_arg += 1 + kw->skip;
4515 goto out;
4516 }
4517 }
4518 free(err);
4519 cur_arg += 1 + kw->skip;
4520 continue;
4521 }
4522
4523 err = NULL;
4524 if (!srv_dumped) {
4525 srv_dump_kws(&err);
4526 indent_msg(&err, 4);
4527 srv_dumped = 1;
4528 }
4529
4530 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4531 file, linenum, args[0], args[1], args[cur_arg],
4532 err ? " Registered keywords :" : "", err ? err : "");
4533 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004534
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 }
4538 }
4539
4540 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004541 if (newsrv->trackit) {
4542 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4543 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004546 }
4547
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004548 /* If neither a port nor an addr was specified and no check transport
4549 * layer is forced, then the transport layer used by the checks is the
4550 * same as for the production traffic. Otherwise we use raw_sock by
4551 * default, unless one is specified.
4552 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004553 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004554#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004555 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004556#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004557 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4558 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004559 /* try to get the port from check.addr if check.port not set */
4560 if (!newsrv->check.port)
4561 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004562
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004563 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4564 newsrv->check.port = realport; /* by default */
4565 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004566 /* not yet valid, because no port was set on
4567 * the server either. We'll check if we have
4568 * a known port on the first listener.
4569 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004570 struct listener *l;
4571
4572 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004573 newsrv->check.port = get_host_port(&l->addr);
4574 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004575 break;
4576 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004577 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004578 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4580 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004584
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004585 /* Allocate buffer for check requests... */
4586 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004587 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4588 err_code |= ERR_ALERT | ERR_ABORT;
4589 goto out;
4590 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004591 newsrv->check.bi->size = global.tune.chksize;
4592
4593 /* Allocate buffer for check responses... */
4594 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4595 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4596 err_code |= ERR_ALERT | ERR_ABORT;
4597 goto out;
4598 }
4599 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004600
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004601 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004602 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004603 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4604 err_code |= ERR_ALERT | ERR_ABORT;
4605 goto out;
4606 }
4607
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004608 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4609 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 newsrv->state |= SRV_CHECKED;
4611 }
4612
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004613 if (!defsrv) {
4614 if (newsrv->state & SRV_BACKUP)
4615 curproxy->srv_bck++;
4616 else
4617 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004618
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004619 newsrv->prev_state = newsrv->state;
4620 }
William Lallemanda73203e2012-03-12 12:48:57 +01004621 }
4622
4623 else if (strcmp(args[0], "unique-id-format") == 0) {
4624 if (!*(args[1])) {
4625 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
4628 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004629 free(curproxy->uniqueid_format_string);
4630 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004631 }
William Lallemanda73203e2012-03-12 12:48:57 +01004632
4633 else if (strcmp(args[0], "unique-id-header") == 0) {
4634 if (!*(args[1])) {
4635 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
4638 }
4639 free(curproxy->header_unique_id);
4640 curproxy->header_unique_id = strdup(args[1]);
4641 }
4642
William Lallemand723b73a2012-02-08 16:37:49 +01004643 else if (strcmp(args[0], "log-format") == 0) {
4644 if (!*(args[1])) {
4645 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004649
4650 if (curproxy->logformat_string != default_http_log_format &&
4651 curproxy->logformat_string != default_tcp_log_format &&
4652 curproxy->logformat_string != clf_http_log_format)
4653 free(curproxy->logformat_string);
4654 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 }
William Lallemand723b73a2012-02-08 16:37:49 +01004656
William Lallemand0f99e342011-10-12 17:50:54 +02004657 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4658 /* delete previous herited or defined syslog servers */
4659 struct logsrv *back;
4660
4661 if (*(args[1]) != 0) {
4662 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
4665 }
4666
William Lallemand723b73a2012-02-08 16:37:49 +01004667 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4668 LIST_DEL(&tmplogsrv->list);
4669 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004670 }
4671 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004672 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004673 struct logsrv *logsrv;
4674
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004676 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004677 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004678 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004679 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004680 LIST_INIT(&node->list);
4681 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 }
4684 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004685
4686 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687
William Lallemand0f99e342011-10-12 17:50:54 +02004688 logsrv->facility = get_log_facility(args[2]);
4689 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
4693
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 }
4695
William Lallemand0f99e342011-10-12 17:50:54 +02004696 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004698 logsrv->level = get_log_level(args[3]);
4699 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
4703
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 }
4705 }
4706
William Lallemand0f99e342011-10-12 17:50:54 +02004707 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004708 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004709 logsrv->minlvl = get_log_level(args[4]);
4710 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004711 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004715 }
4716 }
4717
Robert Tsai81ae1952007-12-05 10:47:29 +01004718 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004719 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004720 if (!sk) {
4721 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004722 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004723 err_code |= ERR_ALERT | ERR_FATAL;
4724 goto out;
4725 }
William Lallemand0f99e342011-10-12 17:50:54 +02004726 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004727 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004728 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004729 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004730 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
William Lallemand0f99e342011-10-12 17:50:54 +02004734 logsrv->addr = *sk;
4735 if (!get_host_port(&logsrv->addr))
4736 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 }
William Lallemand0f99e342011-10-12 17:50:54 +02004738
4739 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
4741 else {
4742 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4743 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
4747 }
4748 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004749 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004750 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751
Willy Tarreau977b8e42006-12-29 14:19:17 +01004752 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004753 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004754
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4757 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004761
4762 /* we must first clear any optional default setting */
4763 curproxy->options &= ~PR_O_TPXY_MASK;
4764 free(curproxy->iface_name);
4765 curproxy->iface_name = NULL;
4766 curproxy->iface_len = 0;
4767
Willy Tarreaud5191e72010-02-09 20:50:45 +01004768 sk = str2sa(args[1]);
4769 if (!sk) {
4770 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
4773 }
4774 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004776
4777 cur_arg = 2;
4778 while (*(args[cur_arg])) {
4779 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004780#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4781#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004782 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4783 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4784 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004787 }
4788#endif
4789 if (!*args[cur_arg + 1]) {
4790 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4791 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004794 }
4795
4796 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004797 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798 curproxy->options |= PR_O_TPXY_CLI;
4799 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004800 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004802 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4803 char *name, *end;
4804
4805 name = args[cur_arg+1] + 7;
4806 while (isspace(*name))
4807 name++;
4808
4809 end = name;
4810 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4811 end++;
4812
4813 curproxy->options &= ~PR_O_TPXY_MASK;
4814 curproxy->options |= PR_O_TPXY_DYN;
4815 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4816 curproxy->bind_hdr_len = end - name;
4817 memcpy(curproxy->bind_hdr_name, name, end - name);
4818 curproxy->bind_hdr_name[end-name] = '\0';
4819 curproxy->bind_hdr_occ = -1;
4820
4821 /* now look for an occurrence number */
4822 while (isspace(*end))
4823 end++;
4824 if (*end == ',') {
4825 end++;
4826 name = end;
4827 if (*end == '-')
4828 end++;
4829 while (isdigit(*end))
4830 end++;
4831 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4832 }
4833
4834 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4835 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4836 " occurrences values smaller than %d.\n",
4837 file, linenum, MAX_HDR_HISTORY);
4838 err_code |= ERR_ALERT | ERR_FATAL;
4839 goto out;
4840 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004841 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004842 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004843 if (!sk) {
4844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4845 err_code |= ERR_ALERT | ERR_FATAL;
4846 goto out;
4847 }
4848 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004849 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004850 }
4851 global.last_checks |= LSTCHK_NETADM;
4852#if !defined(CONFIG_HAP_LINUX_TPROXY)
4853 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004854#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004855#else /* no TPROXY support */
4856 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004857 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004860#endif
4861 cur_arg += 2;
4862 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004863 }
4864
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004865 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4866#ifdef SO_BINDTODEVICE
4867 if (!*args[cur_arg + 1]) {
4868 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004872 }
4873 if (curproxy->iface_name)
4874 free(curproxy->iface_name);
4875
4876 curproxy->iface_name = strdup(args[cur_arg + 1]);
4877 curproxy->iface_len = strlen(curproxy->iface_name);
4878 global.last_checks |= LSTCHK_NETADM;
4879#else
4880 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4881 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004884#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004885 cur_arg += 2;
4886 continue;
4887 }
4888 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004889 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004894 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4895 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4896 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4903 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907
4908 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004909 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004910 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004916 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004917 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004923 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004924 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
4928 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004930 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004931 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004934 }
4935 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004937 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004938 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004942 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004944 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004945 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004947 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004948 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004949 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004951 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004952 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004954 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004955 }
4956 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004958 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004959 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004961 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4966 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970
4971 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004972 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004973 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
4977 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004979 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004980 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 }
4984 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004986 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004987 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004992 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004993 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004994 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005000 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005001 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005005 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005007 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005008 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005013 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005014
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 if (curproxy == &defproxy) {
5016 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005020 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 if (*(args[1]) == 0) {
5024 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005028
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005029 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005030 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5031 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5032 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
5036 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5037 }
5038 else if (*args[2]) {
5039 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5040 file, linenum, args[0], args[2]);
5041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
5043 }
5044
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005045 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005046 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005047 wl->s = strdup(args[1]);
5048 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005049 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
5051 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005058
Willy Tarreauade5ec42010-01-28 19:33:49 +01005059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005060 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005061 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005067 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005074 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
5079 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
5086
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005088 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005089 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
5093 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005095 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005096 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 }
5100 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005102 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005103 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 }
5107 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005108 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005109
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 if (curproxy == &defproxy) {
5111 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005115 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 if (*(args[1]) == 0) {
5119 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005124 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005125 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5126 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5127 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131 err_code |= warnif_cond_requires_req(cond, file, linenum);
5132 }
5133 else if (*args[2]) {
5134 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5135 file, linenum, args[0], args[2]);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005140 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005141 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005142 wl->s = strdup(args[1]);
5143 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 }
5145 else if (!strcmp(args[0], "errorloc") ||
5146 !strcmp(args[0], "errorloc302") ||
5147 !strcmp(args[0], "errorloc303")) { /* error location */
5148 int errnum, errlen;
5149 char *err;
5150
Willy Tarreau977b8e42006-12-29 14:19:17 +01005151 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005153
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005155 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
5159
5160 errnum = atol(args[1]);
5161 if (!strcmp(args[0], "errorloc303")) {
5162 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5163 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5164 } else {
5165 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5166 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5167 }
5168
Willy Tarreau0f772532006-12-23 20:51:41 +01005169 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5170 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005171 chunk_destroy(&curproxy->errmsg[rc]);
5172 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005173 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005176
5177 if (rc >= HTTP_ERR_SIZE) {
5178 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5179 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 free(err);
5181 }
5182 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005183 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5184 int errnum, errlen, fd;
5185 char *err;
5186 struct stat stat;
5187
5188 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005190
5191 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005192 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005195 }
5196
5197 fd = open(args[2], O_RDONLY);
5198 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5199 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5200 file, linenum, args[2], args[1]);
5201 if (fd >= 0)
5202 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005205 }
5206
Willy Tarreau27a674e2009-08-17 07:23:33 +02005207 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005208 errlen = stat.st_size;
5209 } else {
5210 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005211 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005212 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005213 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005214 }
5215
5216 err = malloc(errlen); /* malloc() must succeed during parsing */
5217 errnum = read(fd, err, errlen);
5218 if (errnum != errlen) {
5219 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5220 file, linenum, args[2], args[1]);
5221 close(fd);
5222 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005225 }
5226 close(fd);
5227
5228 errnum = atol(args[1]);
5229 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5230 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005231 chunk_destroy(&curproxy->errmsg[rc]);
5232 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005233 break;
5234 }
5235 }
5236
5237 if (rc >= HTTP_ERR_SIZE) {
5238 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5239 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005241 free(err);
5242 }
5243 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005244 else if (!strcmp(args[0], "compression")) {
5245 struct comp *comp;
5246 if (curproxy->comp == NULL) {
5247 comp = calloc(1, sizeof(struct comp));
5248 curproxy->comp = comp;
5249 } else {
5250 comp = curproxy->comp;
5251 }
5252
5253 if (!strcmp(args[1], "algo")) {
5254 int cur_arg;
5255 cur_arg = 2;
5256 if (!*args[cur_arg]) {
5257 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5258 file, linenum, args[0]);
5259 err_code |= ERR_ALERT | ERR_FATAL;
5260 goto out;
5261 }
5262 while (*(args[cur_arg])) {
5263 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5264 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5265 file, linenum, args[0], args[cur_arg]);
5266 err_code |= ERR_ALERT | ERR_FATAL;
5267 goto out;
5268 }
5269 cur_arg ++;
5270 continue;
5271 }
5272 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005273 else if (!strcmp(args[1], "offload")) {
5274 comp->offload = 1;
5275 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005276 else if (!strcmp(args[1], "type")) {
5277 int cur_arg;
5278 cur_arg = 2;
5279 if (!*args[cur_arg]) {
5280 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5281 file, linenum, args[0]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 while (*(args[cur_arg])) {
5286 comp_append_type(comp, args[cur_arg]);
5287 cur_arg ++;
5288 continue;
5289 }
5290 }
5291 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005292 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005293 file, linenum, args[0]);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005299 struct cfg_kw_list *kwl;
5300 int index;
5301
5302 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5303 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5304 if (kwl->kw[index].section != CFG_LISTEN)
5305 continue;
5306 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5307 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005308 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005309 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005310 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_ALERT | ERR_FATAL;
5312 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005313 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005314 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005315 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005316 err_code |= ERR_WARN;
5317 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005318 }
Willy Tarreau93893792009-07-23 13:19:11 +02005319 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005320 }
5321 }
5322 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005323
Willy Tarreau6daf3432008-01-22 16:44:08 +01005324 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005325 err_code |= ERR_ALERT | ERR_FATAL;
5326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 }
Willy Tarreau93893792009-07-23 13:19:11 +02005328 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005329 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005330 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331}
5332
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005333int
5334cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5335{
5336
5337 int err_code = 0;
5338 const char *err;
5339
5340 if (!strcmp(args[0], "userlist")) { /* new userlist */
5341 struct userlist *newul;
5342
5343 if (!*args[1]) {
5344 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5345 file, linenum, args[0]);
5346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
5348 }
5349
5350 err = invalid_char(args[1]);
5351 if (err) {
5352 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5353 file, linenum, *err, args[0], args[1]);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357
5358 for (newul = userlist; newul; newul = newul->next)
5359 if (!strcmp(newul->name, args[1])) {
5360 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5361 file, linenum, args[1]);
5362 err_code |= ERR_WARN;
5363 goto out;
5364 }
5365
5366 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5367 if (!newul) {
5368 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5369 err_code |= ERR_ALERT | ERR_ABORT;
5370 goto out;
5371 }
5372
5373 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5374 newul->name = strdup(args[1]);
5375
5376 if (!newul->groupusers | !newul->name) {
5377 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5378 err_code |= ERR_ALERT | ERR_ABORT;
5379 goto out;
5380 }
5381
5382 newul->next = userlist;
5383 userlist = newul;
5384
5385 } else if (!strcmp(args[0], "group")) { /* new group */
5386 int cur_arg, i;
5387 const char *err;
5388
5389 if (!*args[1]) {
5390 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5391 file, linenum, args[0]);
5392 err_code |= ERR_ALERT | ERR_FATAL;
5393 goto out;
5394 }
5395
5396 err = invalid_char(args[1]);
5397 if (err) {
5398 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5399 file, linenum, *err, args[0], args[1]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403
5404 for(i = 0; i < userlist->grpcnt; i++)
5405 if (!strcmp(userlist->groups[i], args[1])) {
5406 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5407 file, linenum, args[1], userlist->name);
5408 err_code |= ERR_ALERT;
5409 goto out;
5410 }
5411
5412 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5413 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5414 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
5417 }
5418
5419 cur_arg = 2;
5420
5421 while (*args[cur_arg]) {
5422 if (!strcmp(args[cur_arg], "users")) {
5423 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5424 cur_arg += 2;
5425 continue;
5426 } else {
5427 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5428 file, linenum, args[0]);
5429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
5431 }
5432 }
5433
5434 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5435 } else if (!strcmp(args[0], "user")) { /* new user */
5436 struct auth_users *newuser;
5437 int cur_arg;
5438
5439 if (!*args[1]) {
5440 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5441 file, linenum, args[0]);
5442 err_code |= ERR_ALERT | ERR_FATAL;
5443 goto out;
5444 }
5445
5446 for (newuser = userlist->users; newuser; newuser = newuser->next)
5447 if (!strcmp(newuser->user, args[1])) {
5448 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5449 file, linenum, args[1], userlist->name);
5450 err_code |= ERR_ALERT;
5451 goto out;
5452 }
5453
5454 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5455 if (!newuser) {
5456 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5457 err_code |= ERR_ALERT | ERR_ABORT;
5458 goto out;
5459 }
5460
5461 newuser->user = strdup(args[1]);
5462
5463 newuser->next = userlist->users;
5464 userlist->users = newuser;
5465
5466 cur_arg = 2;
5467
5468 while (*args[cur_arg]) {
5469 if (!strcmp(args[cur_arg], "password")) {
5470#ifndef CONFIG_HAP_CRYPT
5471 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5472 file, linenum);
5473 err_code |= ERR_ALERT;
5474#endif
5475 newuser->pass = strdup(args[cur_arg + 1]);
5476 cur_arg += 2;
5477 continue;
5478 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5479 newuser->pass = strdup(args[cur_arg + 1]);
5480 newuser->flags |= AU_O_INSECURE;
5481 cur_arg += 2;
5482 continue;
5483 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005484 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005485 cur_arg += 2;
5486 continue;
5487 } else {
5488 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5489 file, linenum, args[0]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493 }
5494 } else {
5495 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 }
5498
5499out:
5500 return err_code;
5501}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502
5503/*
5504 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005505 * Returns the error code, 0 if OK, or any combination of :
5506 * - ERR_ABORT: must abort ASAP
5507 * - ERR_FATAL: we can continue parsing but not start the service
5508 * - ERR_WARN: a warning has been emitted
5509 * - ERR_ALERT: an alert has been emitted
5510 * Only the two first ones can stop processing, the two others are just
5511 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005513int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005515 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 FILE *f;
5517 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005519 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521 if ((f=fopen(file,"r")) == NULL)
5522 return -1;
5523
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005524 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005525 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005526 char *end;
5527 char *args[MAX_LINE_ARGS + 1];
5528 char *line = thisline;
5529
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 linenum++;
5531
5532 end = line + strlen(line);
5533
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005534 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5535 /* Check if we reached the limit and the last char is not \n.
5536 * Watch out for the last line without the terminating '\n'!
5537 */
5538 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005539 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005540 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005541 }
5542
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005544 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 line++;
5546
5547 arg = 0;
5548 args[arg] = line;
5549
5550 while (*line && arg < MAX_LINE_ARGS) {
5551 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5552 * C equivalent value. Other combinations left unchanged (eg: \1).
5553 */
5554 if (*line == '\\') {
5555 int skip = 0;
5556 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5557 *line = line[1];
5558 skip = 1;
5559 }
5560 else if (line[1] == 'r') {
5561 *line = '\r';
5562 skip = 1;
5563 }
5564 else if (line[1] == 'n') {
5565 *line = '\n';
5566 skip = 1;
5567 }
5568 else if (line[1] == 't') {
5569 *line = '\t';
5570 skip = 1;
5571 }
5572 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005573 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 unsigned char hex1, hex2;
5575 hex1 = toupper(line[2]) - '0';
5576 hex2 = toupper(line[3]) - '0';
5577 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5578 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5579 *line = (hex1<<4) + hex2;
5580 skip = 3;
5581 }
5582 else {
5583 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005584 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
5586 }
5587 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005588 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 end -= skip;
5590 }
5591 line++;
5592 }
5593 else if (*line == '#' || *line == '\n' || *line == '\r') {
5594 /* end of string, end of loop */
5595 *line = 0;
5596 break;
5597 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005598 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005600 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005601 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 line++;
5603 args[++arg] = line;
5604 }
5605 else {
5606 line++;
5607 }
5608 }
5609
5610 /* empty line */
5611 if (!**args)
5612 continue;
5613
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005614 if (*line) {
5615 /* we had to stop due to too many args.
5616 * Let's terminate the string, print the offending part then cut the
5617 * last arg.
5618 */
5619 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5620 line++;
5621 *line = '\0';
5622
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005623 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005624 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 args[arg] = line;
5627 }
5628
Willy Tarreau540abe42007-05-02 20:50:16 +02005629 /* zero out remaining args and ensure that at least one entry
5630 * is zeroed out.
5631 */
5632 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 args[arg] = line;
5634 }
5635
Willy Tarreau3842f002009-06-14 11:39:52 +02005636 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005637 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005638 char *tmp;
5639
Willy Tarreau3842f002009-06-14 11:39:52 +02005640 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005641 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005642 for (arg=0; *args[arg+1]; arg++)
5643 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005644 *tmp = '\0'; // fix the next arg to \0
5645 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005646 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005647 else if (!strcmp(args[0], "default")) {
5648 kwm = KWM_DEF;
5649 for (arg=0; *args[arg+1]; arg++)
5650 args[arg] = args[arg+1]; // shift args after inversion
5651 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005652
William Lallemand0f99e342011-10-12 17:50:54 +02005653 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5654 strcmp(args[0], "log") != 0) {
5655 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005656 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005657 }
5658
Willy Tarreau977b8e42006-12-29 14:19:17 +01005659 if (!strcmp(args[0], "listen") ||
5660 !strcmp(args[0], "frontend") ||
5661 !strcmp(args[0], "backend") ||
5662 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005663 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005665 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005666 cursection = strdup(args[0]);
5667 }
5668 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005670 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005671 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005672 }
5673 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005674 confsect = CFG_USERLIST;
5675 free(cursection);
5676 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005677 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005678 else if (!strcmp(args[0], "peers")) {
5679 confsect = CFG_PEERS;
5680 free(cursection);
5681 cursection = strdup(args[0]);
5682 }
5683
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 /* else it's a section keyword */
5685
5686 switch (confsect) {
5687 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005688 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 break;
5690 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005691 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 case CFG_USERLIST:
5694 err_code |= cfg_parse_users(file, linenum, args, kwm);
5695 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005696 case CFG_PEERS:
5697 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5698 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005700 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005701 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005703
5704 if (err_code & ERR_ABORT)
5705 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005707 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005708 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005710 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005711}
5712
Willy Tarreaubb925012009-07-23 13:36:36 +02005713/*
5714 * Returns the error code, 0 if OK, or any combination of :
5715 * - ERR_ABORT: must abort ASAP
5716 * - ERR_FATAL: we can continue parsing but not start the service
5717 * - ERR_WARN: a warning has been emitted
5718 * - ERR_ALERT: an alert has been emitted
5719 * Only the two first ones can stop processing, the two others are just
5720 * indicators.
5721 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005722int check_config_validity()
5723{
5724 int cfgerr = 0;
5725 struct proxy *curproxy = NULL;
5726 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005727 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005728 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005729 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005730 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005732 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 /*
5734 * Now, check for the integrity of all that we have collected.
5735 */
5736
5737 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005738 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005739
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005740 /* first, we will invert the proxy list order */
5741 curproxy = NULL;
5742 while (proxy) {
5743 struct proxy *next;
5744
5745 next = proxy->next;
5746 proxy->next = curproxy;
5747 curproxy = proxy;
5748 if (!next)
5749 break;
5750 proxy = next;
5751 }
5752
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005754 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005755 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005757 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005758 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005759 unsigned int next_id;
5760
Willy Tarreau050536d2012-10-04 08:47:34 +02005761 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005762 /* proxy ID not set, use automatic numbering with first
5763 * spare entry starting with next_pxid.
5764 */
5765 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5766 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5767 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005768 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005769 next_pxid++;
5770
Willy Tarreau55ea7572007-06-17 19:56:27 +02005771
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005773 /* ensure we don't keep listeners uselessly bound */
5774 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 curproxy = curproxy->next;
5776 continue;
5777 }
5778
Willy Tarreauff01a212009-03-15 13:46:16 +01005779 switch (curproxy->mode) {
5780 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005781 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005782 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005783 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5784 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005785 cfgerr++;
5786 }
5787
5788 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005789 Warning("config : servers will be ignored for %s '%s'.\n",
5790 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005791 break;
5792
5793 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005794 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005795 break;
5796
5797 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005798 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005799 break;
5800 }
5801
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005802 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005803 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005804 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005805 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5806 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005807 cfgerr++;
5808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005810 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005811 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5812 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005813 cfgerr++;
5814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005816 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005817 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5818 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005819 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005820 }
5821 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005822 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005823 /* If no LB algo is set in a backend, and we're not in
5824 * transparent mode, dispatch mode nor proxy mode, we
5825 * want to use balance roundrobin by default.
5826 */
5827 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5828 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 }
5830 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005831
Willy Tarreau1620ec32011-08-06 17:05:02 +02005832 if (curproxy->options & PR_O_DISPATCH)
5833 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5834 else if (curproxy->options & PR_O_HTTP_PROXY)
5835 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5836 else if (curproxy->options & PR_O_TRANSP)
5837 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005838
Willy Tarreau1620ec32011-08-06 17:05:02 +02005839 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5840 if (curproxy->options & PR_O_DISABLE404) {
5841 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5842 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5843 err_code |= ERR_WARN;
5844 curproxy->options &= ~PR_O_DISABLE404;
5845 }
5846 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5847 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5848 "send-state", proxy_type_str(curproxy), curproxy->id);
5849 err_code |= ERR_WARN;
5850 curproxy->options &= ~PR_O2_CHK_SNDST;
5851 }
Willy Tarreauef781042010-01-27 11:53:01 +01005852 }
5853
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005854 /* if a default backend was specified, let's find it */
5855 if (curproxy->defbe.name) {
5856 struct proxy *target;
5857
Alex Williams96532db2009-11-01 21:27:13 -05005858 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005859 if (!target) {
5860 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5861 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005862 cfgerr++;
5863 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005864 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5865 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005866 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005867 } else {
5868 free(curproxy->defbe.name);
5869 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005870 /* we force the backend to be present on at least all of
5871 * the frontend's processes.
5872 */
5873 target->bind_proc = curproxy->bind_proc ?
5874 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005875
5876 /* Emit a warning if this proxy also has some servers */
5877 if (curproxy->srv) {
5878 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5879 curproxy->id);
5880 err_code |= ERR_WARN;
5881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 }
5883 }
5884
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005885 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005886 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5887 /* map jump target for ACT_SETBE in req_rep chain */
5888 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005889 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005890 struct proxy *target;
5891
Willy Tarreaua496b602006-12-17 23:15:24 +01005892 if (exp->action != ACT_SETBE)
5893 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005894
Alex Williams96532db2009-11-01 21:27:13 -05005895 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005896 if (!target) {
5897 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5898 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005899 cfgerr++;
5900 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005901 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5902 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005903 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005904 } else {
5905 free((void *)exp->replace);
5906 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005907 /* we force the backend to be present on at least all of
5908 * the frontend's processes.
5909 */
5910 target->bind_proc = curproxy->bind_proc ?
5911 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005912 }
5913 }
5914 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005915
5916 /* find the target proxy for 'use_backend' rules */
5917 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005918 struct proxy *target;
5919
Alex Williams96532db2009-11-01 21:27:13 -05005920 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005921
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005922 if (!target) {
5923 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5924 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005925 cfgerr++;
5926 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005927 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5928 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005929 cfgerr++;
5930 } else {
5931 free((void *)rule->be.name);
5932 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005933 /* we force the backend to be present on at least all of
5934 * the frontend's processes.
5935 */
5936 target->bind_proc = curproxy->bind_proc ?
5937 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005938 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005939 }
5940
5941 /* find the target proxy for 'use_backend' rules */
5942 list_for_each_entry(srule, &curproxy->server_rules, list) {
5943 struct server *target = findserver(curproxy, srule->srv.name);
5944
5945 if (!target) {
5946 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5947 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5948 cfgerr++;
5949 continue;
5950 }
5951 free((void *)srule->srv.name);
5952 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005953 }
5954
Emeric Brunb982a3d2010-01-04 15:45:53 +01005955 /* find the target table for 'stick' rules */
5956 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5957 struct proxy *target;
5958
Emeric Brun1d33b292010-01-04 15:47:17 +01005959 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5960 if (mrule->flags & STK_IS_STORE)
5961 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5962
Emeric Brunb982a3d2010-01-04 15:45:53 +01005963 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005964 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005965 else
5966 target = curproxy;
5967
5968 if (!target) {
5969 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5970 curproxy->id, mrule->table.name);
5971 cfgerr++;
5972 }
5973 else if (target->table.size == 0) {
5974 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5975 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5976 cfgerr++;
5977 }
Willy Tarreau12785782012-04-27 21:37:17 +02005978 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5979 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005980 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5981 cfgerr++;
5982 }
5983 else {
5984 free((void *)mrule->table.name);
5985 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005986 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005987 }
5988 }
5989
5990 /* find the target table for 'store response' rules */
5991 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5992 struct proxy *target;
5993
Emeric Brun1d33b292010-01-04 15:47:17 +01005994 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5995
Emeric Brunb982a3d2010-01-04 15:45:53 +01005996 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005997 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005998 else
5999 target = curproxy;
6000
6001 if (!target) {
6002 Alert("Proxy '%s': unable to find store table '%s'.\n",
6003 curproxy->id, mrule->table.name);
6004 cfgerr++;
6005 }
6006 else if (target->table.size == 0) {
6007 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6008 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6009 cfgerr++;
6010 }
Willy Tarreau12785782012-04-27 21:37:17 +02006011 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6012 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006013 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6014 cfgerr++;
6015 }
6016 else {
6017 free((void *)mrule->table.name);
6018 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006019 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006020 }
6021 }
6022
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006023 /* find the target table for 'tcp-request' layer 4 rules */
6024 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6025 struct proxy *target;
6026
Willy Tarreau56123282010-08-06 19:06:56 +02006027 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006028 continue;
6029
6030 if (trule->act_prm.trk_ctr.table.n)
6031 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6032 else
6033 target = curproxy;
6034
6035 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006036 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6037 curproxy->id, trule->act_prm.trk_ctr.table.n,
6038 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006039 cfgerr++;
6040 }
6041 else if (target->table.size == 0) {
6042 Alert("Proxy '%s': table '%s' used but not configured.\n",
6043 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6044 cfgerr++;
6045 }
6046 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006047 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006048 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6049 cfgerr++;
6050 }
6051 else {
6052 free(trule->act_prm.trk_ctr.table.n);
6053 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006054 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006055 * to pass a list of counters to track and allocate them right here using
6056 * stktable_alloc_data_type().
6057 */
6058 }
6059 }
6060
Willy Tarreaud1f96522010-08-03 19:34:32 +02006061 /* find the target table for 'tcp-request' layer 6 rules */
6062 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6063 struct proxy *target;
6064
Willy Tarreau56123282010-08-06 19:06:56 +02006065 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006066 continue;
6067
6068 if (trule->act_prm.trk_ctr.table.n)
6069 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6070 else
6071 target = curproxy;
6072
6073 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006074 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6075 curproxy->id, trule->act_prm.trk_ctr.table.n,
6076 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006077 cfgerr++;
6078 }
6079 else if (target->table.size == 0) {
6080 Alert("Proxy '%s': table '%s' used but not configured.\n",
6081 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6082 cfgerr++;
6083 }
6084 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006085 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006086 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6087 cfgerr++;
6088 }
6089 else {
6090 free(trule->act_prm.trk_ctr.table.n);
6091 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006092 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006093 * to pass a list of counters to track and allocate them right here using
6094 * stktable_alloc_data_type().
6095 */
6096 }
6097 }
6098
Emeric Brun32da3c42010-09-23 18:39:19 +02006099 if (curproxy->table.peers.name) {
6100 struct peers *curpeers = peers;
6101
6102 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6103 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6104 free((void *)curproxy->table.peers.name);
6105 curproxy->table.peers.p = peers;
6106 break;
6107 }
6108 }
6109
6110 if (!curpeers) {
6111 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6112 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006113 free((void *)curproxy->table.peers.name);
6114 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006115 cfgerr++;
6116 }
6117 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006118 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6119 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006120 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006121 cfgerr++;
6122 }
6123 }
6124
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006125 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006126 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006127 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6128 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6129 "proxy", curproxy->id);
6130 cfgerr++;
6131 goto out_uri_auth_compat;
6132 }
6133
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006134 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006135 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006136 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006137 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006138
Willy Tarreau95fa4692010-02-01 13:05:50 +01006139 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6140 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006141
6142 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006143 uri_auth_compat_req[i++] = "realm";
6144 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6145 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006146
Willy Tarreau95fa4692010-02-01 13:05:50 +01006147 uri_auth_compat_req[i++] = "unless";
6148 uri_auth_compat_req[i++] = "{";
6149 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6150 uri_auth_compat_req[i++] = "}";
6151 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006152
Willy Tarreauff011f22011-01-06 17:51:27 +01006153 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6154 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006155 cfgerr++;
6156 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006157 }
6158
Willy Tarreauff011f22011-01-06 17:51:27 +01006159 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006160
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006161 if (curproxy->uri_auth->auth_realm) {
6162 free(curproxy->uri_auth->auth_realm);
6163 curproxy->uri_auth->auth_realm = NULL;
6164 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006165
6166 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006167 }
6168out_uri_auth_compat:
6169
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006170 cfgerr += acl_find_targets(curproxy);
6171
Willy Tarreau2738a142006-07-08 17:28:09 +02006172 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006173 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006174 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006175 (!curproxy->timeout.connect ||
6176 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006177 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006178 " | While not properly invalid, you will certainly encounter various problems\n"
6179 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006180 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006182 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006183 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006184
Willy Tarreau1fa31262007-12-03 00:36:16 +01006185 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6186 * We must still support older configurations, so let's find out whether those
6187 * parameters have been set or must be copied from contimeouts.
6188 */
6189 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006190 if (!curproxy->timeout.tarpit ||
6191 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006192 /* tarpit timeout not set. We search in the following order:
6193 * default.tarpit, curr.connect, default.connect.
6194 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006195 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006196 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006197 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006198 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006199 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006200 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006201 }
6202 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006203 (!curproxy->timeout.queue ||
6204 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006205 /* queue timeout not set. We search in the following order:
6206 * default.queue, curr.connect, default.connect.
6207 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006208 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006209 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006210 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006211 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006212 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006213 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006214 }
6215 }
6216
Willy Tarreau1620ec32011-08-06 17:05:02 +02006217 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006218 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6219 curproxy->check_req = (char *)malloc(curproxy->check_len);
6220 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006221 }
6222
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006223 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006224 if (curproxy->nb_req_cap) {
6225 if (curproxy->mode == PR_MODE_HTTP) {
6226 curproxy->req_cap_pool = create_pool("ptrcap",
6227 curproxy->nb_req_cap * sizeof(char *),
6228 MEM_F_SHARED);
6229 } else {
6230 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6231 proxy_type_str(curproxy), curproxy->id);
6232 err_code |= ERR_WARN;
6233 curproxy->to_log &= ~LW_REQHDR;
6234 curproxy->nb_req_cap = 0;
6235 }
6236 }
6237
6238 if (curproxy->nb_rsp_cap) {
6239 if (curproxy->mode == PR_MODE_HTTP) {
6240 curproxy->rsp_cap_pool = create_pool("ptrcap",
6241 curproxy->nb_rsp_cap * sizeof(char *),
6242 MEM_F_SHARED);
6243 } else {
6244 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6245 proxy_type_str(curproxy), curproxy->id);
6246 err_code |= ERR_WARN;
6247 curproxy->to_log &= ~LW_REQHDR;
6248 curproxy->nb_rsp_cap = 0;
6249 }
6250 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006251
Willy Tarreau196729e2012-05-31 19:30:26 +02006252 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006253 if (!(curproxy->cap & PR_CAP_FE)) {
6254 if (curproxy->logformat_string != default_http_log_format &&
6255 curproxy->logformat_string != default_tcp_log_format &&
6256 curproxy->logformat_string != clf_http_log_format)
6257 free(curproxy->logformat_string);
6258 curproxy->logformat_string = NULL;
6259 }
6260
Willy Tarreau196729e2012-05-31 19:30:26 +02006261 if (curproxy->logformat_string)
6262 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6263
6264 if (curproxy->uniqueid_format_string)
6265 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6266
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 /* first, we will invert the servers list order */
6268 newsrv = NULL;
6269 while (curproxy->srv) {
6270 struct server *next;
6271
6272 next = curproxy->srv->next;
6273 curproxy->srv->next = newsrv;
6274 newsrv = curproxy->srv;
6275 if (!next)
6276 break;
6277 curproxy->srv = next;
6278 }
6279
Willy Tarreaudd701652010-05-25 23:03:02 +02006280 /* assign automatic UIDs to servers which don't have one yet */
6281 next_id = 1;
6282 newsrv = curproxy->srv;
6283 while (newsrv != NULL) {
6284 if (!newsrv->puid) {
6285 /* server ID not set, use automatic numbering with first
6286 * spare entry starting with next_svid.
6287 */
6288 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6289 newsrv->conf.id.key = newsrv->puid = next_id;
6290 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6291 }
6292 next_id++;
6293 newsrv = newsrv->next;
6294 }
6295
Willy Tarreau20697042007-11-15 23:26:18 +01006296 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006297 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298
Willy Tarreau62c3be22012-01-20 13:12:32 +01006299 /*
6300 * If this server supports a maxconn parameter, it needs a dedicated
6301 * tasks to fill the emptied slots when a connection leaves.
6302 * Also, resolve deferred tracking dependency if needed.
6303 */
6304 newsrv = curproxy->srv;
6305 while (newsrv != NULL) {
6306 if (newsrv->minconn > newsrv->maxconn) {
6307 /* Only 'minconn' was specified, or it was higher than or equal
6308 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6309 * this will avoid further useless expensive computations.
6310 */
6311 newsrv->maxconn = newsrv->minconn;
6312 } else if (newsrv->maxconn && !newsrv->minconn) {
6313 /* minconn was not specified, so we set it to maxconn */
6314 newsrv->minconn = newsrv->maxconn;
6315 }
6316
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006317#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006318 if (newsrv->use_ssl || newsrv->check.use_ssl)
6319 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006320#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006321
Willy Tarreau62c3be22012-01-20 13:12:32 +01006322 if (newsrv->trackit) {
6323 struct proxy *px;
6324 struct server *srv;
6325 char *pname, *sname;
6326
6327 pname = newsrv->trackit;
6328 sname = strrchr(pname, '/');
6329
6330 if (sname)
6331 *sname++ = '\0';
6332 else {
6333 sname = pname;
6334 pname = NULL;
6335 }
6336
6337 if (pname) {
6338 px = findproxy(pname, PR_CAP_BE);
6339 if (!px) {
6340 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6341 proxy_type_str(curproxy), curproxy->id,
6342 newsrv->id, pname);
6343 cfgerr++;
6344 goto next_srv;
6345 }
6346 } else
6347 px = curproxy;
6348
6349 srv = findserver(px, sname);
6350 if (!srv) {
6351 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6352 proxy_type_str(curproxy), curproxy->id,
6353 newsrv->id, sname);
6354 cfgerr++;
6355 goto next_srv;
6356 }
6357
6358 if (!(srv->state & SRV_CHECKED)) {
6359 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6360 "tracking as it does not have checks enabled.\n",
6361 proxy_type_str(curproxy), curproxy->id,
6362 newsrv->id, px->id, srv->id);
6363 cfgerr++;
6364 goto next_srv;
6365 }
6366
6367 if (curproxy != px &&
6368 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6369 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6370 "tracking: disable-on-404 option inconsistency.\n",
6371 proxy_type_str(curproxy), curproxy->id,
6372 newsrv->id, px->id, srv->id);
6373 cfgerr++;
6374 goto next_srv;
6375 }
6376
6377 /* if the other server is forced disabled, we have to do the same here */
6378 if (srv->state & SRV_MAINTAIN) {
6379 newsrv->state |= SRV_MAINTAIN;
6380 newsrv->state &= ~SRV_RUNNING;
6381 newsrv->health = 0;
6382 }
6383
6384 newsrv->track = srv;
6385 newsrv->tracknext = srv->tracknext;
6386 srv->tracknext = newsrv;
6387
6388 free(newsrv->trackit);
6389 newsrv->trackit = NULL;
6390 }
6391 next_srv:
6392 newsrv = newsrv->next;
6393 }
6394
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006395 /* We have to initialize the server lookup mechanism depending
6396 * on what LB algorithm was choosen.
6397 */
6398
6399 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6400 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6401 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006402 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6403 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6404 init_server_map(curproxy);
6405 } else {
6406 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6407 fwrr_init_server_groups(curproxy);
6408 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006409 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006410
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006411 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006412 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6413 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6414 fwlc_init_server_tree(curproxy);
6415 } else {
6416 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6417 fas_init_server_tree(curproxy);
6418 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006419 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006420
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006421 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006422 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6423 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6424 chash_init_server_tree(curproxy);
6425 } else {
6426 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6427 init_server_map(curproxy);
6428 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006429 break;
6430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431
6432 if (curproxy->options & PR_O_LOGASAP)
6433 curproxy->to_log &= ~LW_BYTES;
6434
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006435 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006436 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006437 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6438 proxy_type_str(curproxy), curproxy->id);
6439 err_code |= ERR_WARN;
6440 }
6441
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006442 if (curproxy->mode != PR_MODE_HTTP) {
6443 int optnum;
6444
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006445 if (curproxy->uri_auth) {
6446 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6447 proxy_type_str(curproxy), curproxy->id);
6448 err_code |= ERR_WARN;
6449 curproxy->uri_auth = NULL;
6450 }
6451
Willy Tarreau87cf5142011-08-19 22:57:24 +02006452 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006453 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6454 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6455 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006456 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006457 }
6458
6459 if (curproxy->options & PR_O_ORGTO) {
6460 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6461 "originalto", proxy_type_str(curproxy), curproxy->id);
6462 err_code |= ERR_WARN;
6463 curproxy->options &= ~PR_O_ORGTO;
6464 }
6465
6466 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6467 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6468 (curproxy->cap & cfg_opts[optnum].cap) &&
6469 (curproxy->options & cfg_opts[optnum].val)) {
6470 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6471 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6472 err_code |= ERR_WARN;
6473 curproxy->options &= ~cfg_opts[optnum].val;
6474 }
6475 }
6476
6477 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6478 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6479 (curproxy->cap & cfg_opts2[optnum].cap) &&
6480 (curproxy->options2 & cfg_opts2[optnum].val)) {
6481 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6482 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6483 err_code |= ERR_WARN;
6484 curproxy->options2 &= ~cfg_opts2[optnum].val;
6485 }
6486 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006487
Willy Tarreauefa5f512010-03-30 20:13:29 +02006488#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006489 if (curproxy->bind_hdr_occ) {
6490 curproxy->bind_hdr_occ = 0;
6491 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6492 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6493 err_code |= ERR_WARN;
6494 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006495#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006496 }
6497
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006499 * ensure that we're not cross-dressing a TCP server into HTTP.
6500 */
6501 newsrv = curproxy->srv;
6502 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006503 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006504 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6505 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006506 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006507 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006508
Willy Tarreau0cec3312011-10-31 13:49:26 +01006509 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6510 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6511 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6512 err_code |= ERR_WARN;
6513 }
6514
Willy Tarreauefa5f512010-03-30 20:13:29 +02006515#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006516 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6517 newsrv->bind_hdr_occ = 0;
6518 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6519 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6520 err_code |= ERR_WARN;
6521 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006522#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006523 newsrv = newsrv->next;
6524 }
6525
Willy Tarreauc1a21672009-08-16 22:37:44 +02006526 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006527 if (!curproxy->accept)
6528 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006529
Willy Tarreauc1a21672009-08-16 22:37:44 +02006530 if (curproxy->tcp_req.inspect_delay ||
6531 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006532 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006533
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006534 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006535 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006536 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006537 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006538
6539 /* both TCP and HTTP must check switching rules */
6540 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6541 }
6542
6543 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006544 if (curproxy->tcp_req.inspect_delay ||
6545 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6546 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6547
Emeric Brun97679e72010-09-23 17:56:44 +02006548 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6549 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6550
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006551 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006552 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006553 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006554 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006555
6556 /* If the backend does requires RDP cookie persistence, we have to
6557 * enable the corresponding analyser.
6558 */
6559 if (curproxy->options2 & PR_O2_RDPC_PRST)
6560 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6561 }
6562
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006563 /* Configure SSL for each bind line.
6564 * Note: if configuration fails at some point, the ->ctx member
6565 * remains NULL so that listeners can later detach.
6566 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006567 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6568 if (!bind_conf->is_ssl)
6569 continue;
6570#ifdef USE_OPENSSL
6571 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006572 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006573 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006574 cfgerr++;
6575 continue;
6576 }
6577
Emeric Brun4b3091e2012-09-24 15:48:52 +02006578 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006579 Alert("Unable to allocate SSL session cache.\n");
6580 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006581 continue;
6582 }
6583
Emeric Brunfc0421f2012-09-07 17:30:07 +02006584 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006585 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006586#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006587 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006588
Willy Tarreaue6b98942007-10-29 01:09:36 +01006589 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006590 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006591 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006592 if (!listener->luid) {
6593 /* listener ID not set, use automatic numbering with first
6594 * spare entry starting with next_luid.
6595 */
6596 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6597 listener->conf.id.key = listener->luid = next_id;
6598 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006599 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006600 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006601
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006602 /* enable separate counters */
6603 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6604 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006605 if (!listener->name)
6606 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006607 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006608
Willy Tarreaue6b98942007-10-29 01:09:36 +01006609 if (curproxy->options & PR_O_TCP_NOLING)
6610 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006611 if (!listener->maxconn)
6612 listener->maxconn = curproxy->maxconn;
6613 if (!listener->backlog)
6614 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006615 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006616 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006617 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006618 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006619
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006620 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6621 listener->options |= LI_O_TCP_RULES;
6622
Willy Tarreaude3041d2010-05-31 10:56:17 +02006623 if (curproxy->mon_mask.s_addr)
6624 listener->options |= LI_O_CHK_MONNET;
6625
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006626 /* smart accept mode is automatic in HTTP mode */
6627 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006628 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006629 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6630 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006631 }
6632
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006633 /* Release unused SSL configs */
6634 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6635 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006636 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006637#ifdef USE_OPENSSL
6638 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006639 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006640 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006641 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006642 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006643#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006644 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006645
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006646 /* Check multi-process mode compatibility for the current proxy */
6647 if (global.nbproc > 1) {
6648 int nbproc = 0;
6649 if (curproxy->bind_proc) {
6650 int proc;
6651 for (proc = 0; proc < global.nbproc; proc++) {
6652 if (curproxy->bind_proc & (1 << proc)) {
6653 nbproc++;
6654 }
6655 }
6656 } else {
6657 nbproc = global.nbproc;
6658 }
6659 if (curproxy->table.peers.name) {
6660 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6661 curproxy->id);
6662 cfgerr++;
6663 }
6664 if (nbproc > 1) {
6665 if (curproxy->uri_auth) {
6666 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6667 curproxy->id);
6668 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6669 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6670 curproxy->id);
6671 }
6672 }
6673 if (curproxy->appsession_name) {
6674 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6675 curproxy->id);
6676 }
6677 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6678 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6679 curproxy->id);
6680 }
6681 }
6682 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006683
6684 /* create the task associated with the proxy */
6685 curproxy->task = task_new();
6686 if (curproxy->task) {
6687 curproxy->task->context = curproxy;
6688 curproxy->task->process = manage_proxy;
6689 /* no need to queue, it will be done automatically if some
6690 * listener gets limited.
6691 */
6692 curproxy->task->expire = TICK_ETERNITY;
6693 } else {
6694 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6695 curproxy->id);
6696 cfgerr++;
6697 }
6698
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699 curproxy = curproxy->next;
6700 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006701
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006702 /* Check multi-process mode compatibility */
6703 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006704 if (global.stats_fe && !global.stats_fe->bind_proc) {
6705 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 +01006706 }
6707 }
6708
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006709 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6710 struct auth_users *curuser;
6711 int g;
6712
6713 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6714 unsigned int group_mask = 0;
6715 char *group = NULL;
6716
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006717 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006718 continue;
6719
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006720 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006721
6722 for (g = 0; g < curuserlist->grpcnt; g++)
6723 if (!strcmp(curuserlist->groups[g], group))
6724 break;
6725
6726 if (g == curuserlist->grpcnt) {
6727 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6728 curuserlist->name, group, curuser->user);
6729 err_code |= ERR_ALERT | ERR_FATAL;
6730 goto out;
6731 }
6732
6733 group_mask |= (1 << g);
6734 }
6735
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006736 free(curuser->u.groups);
6737 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006738 }
6739
6740 for (g = 0; g < curuserlist->grpcnt; g++) {
6741 char *user = NULL;
6742
6743 if (!curuserlist->groupusers[g])
6744 continue;
6745
6746 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6747 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6748 if (!strcmp(curuser->user, user))
6749 break;
6750
6751 if (!curuser) {
6752 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6753 curuserlist->name, user, curuserlist->groups[g]);
6754 err_code |= ERR_ALERT | ERR_FATAL;
6755 goto out;
6756 }
6757
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006758 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006759 }
6760
6761 free(curuserlist->groupusers[g]);
6762 }
6763
6764 free(curuserlist->groupusers);
6765
6766#ifdef DEBUG_AUTH
6767 for (g = 0; g < curuserlist->grpcnt; g++) {
6768 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6769
6770 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006771 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772 fprintf(stderr, " %s", curuser->user);
6773 }
6774
6775 fprintf(stderr, "\n");
6776 }
6777#endif
6778
Willy Tarreaufbb78422011-06-05 15:38:35 +02006779 }
6780
6781 /* automatically compute fullconn if not set. We must not do it in the
6782 * loop above because cross-references are not yet fully resolved.
6783 */
6784 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6785 /* If <fullconn> is not set, let's set it to 10% of the sum of
6786 * the possible incoming frontend's maxconns.
6787 */
6788 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6789 struct proxy *fe;
6790 int total = 0;
6791
6792 /* sum up the number of maxconns of frontends which
6793 * reference this backend at least once or which are
6794 * the same one ('listen').
6795 */
6796 for (fe = proxy; fe; fe = fe->next) {
6797 struct switching_rule *rule;
6798 struct hdr_exp *exp;
6799 int found = 0;
6800
6801 if (!(fe->cap & PR_CAP_FE))
6802 continue;
6803
6804 if (fe == curproxy) /* we're on a "listen" instance */
6805 found = 1;
6806
6807 if (fe->defbe.be == curproxy) /* "default_backend" */
6808 found = 1;
6809
6810 /* check if a "use_backend" rule matches */
6811 if (!found) {
6812 list_for_each_entry(rule, &fe->switching_rules, list) {
6813 if (rule->be.backend == curproxy) {
6814 found = 1;
6815 break;
6816 }
6817 }
6818 }
6819
6820 /* check if a "reqsetbe" rule matches */
6821 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6822 if (exp->action == ACT_SETBE &&
6823 (struct proxy *)exp->replace == curproxy) {
6824 found = 1;
6825 break;
6826 }
6827 }
6828
6829 /* now we've checked all possible ways to reference a backend
6830 * from a frontend.
6831 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006832 if (!found)
6833 continue;
6834 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006835 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006836 /* we have the sum of the maxconns in <total>. We only
6837 * keep 10% of that sum to set the default fullconn, with
6838 * a hard minimum of 1 (to avoid a divide by zero).
6839 */
6840 curproxy->fullconn = (total + 9) / 10;
6841 if (!curproxy->fullconn)
6842 curproxy->fullconn = 1;
6843 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006844 }
6845
Willy Tarreau056f5682010-06-06 15:51:11 +02006846 /* initialize stick-tables on backend capable proxies. This must not
6847 * be done earlier because the data size may be discovered while parsing
6848 * other proxies.
6849 */
6850 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006851 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006852
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006853 /*
6854 * Recount currently required checks.
6855 */
6856
6857 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6858 int optnum;
6859
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006860 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6861 if (curproxy->options & cfg_opts[optnum].val)
6862 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006863
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006864 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6865 if (curproxy->options2 & cfg_opts2[optnum].val)
6866 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006867 }
6868
Willy Tarreau122541c2011-09-07 21:24:49 +02006869 if (peers) {
6870 struct peers *curpeers = peers, **last;
6871 struct peer *p, *pb;
6872
6873 /* Remove all peers sections which don't have a valid listener.
6874 * This can happen when a peers section is never referenced and
6875 * does not contain a local peer.
6876 */
6877 last = &peers;
6878 while (*last) {
6879 curpeers = *last;
6880 if (curpeers->peers_fe) {
6881 last = &curpeers->next;
6882 continue;
6883 }
6884
6885 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6886 curpeers->id, localpeer);
6887
6888 p = curpeers->remote;
6889 while (p) {
6890 pb = p->next;
6891 free(p->id);
6892 free(p);
6893 p = pb;
6894 }
6895
6896 /* Destroy and unlink this curpeers section.
6897 * Note: curpeers is backed up into *last.
6898 */
6899 free(curpeers->id);
6900 curpeers = curpeers->next;
6901 free(*last);
6902 *last = curpeers;
6903 }
6904 }
6905
Willy Tarreauac1932d2011-10-24 19:14:41 +02006906 if (!global.tune.max_http_hdr)
6907 global.tune.max_http_hdr = MAX_HTTP_HDR;
6908
Willy Tarreau34eb6712011-10-24 18:15:04 +02006909 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006910 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006911 MEM_F_SHARED);
6912
Willy Tarreaubb925012009-07-23 13:36:36 +02006913 if (cfgerr > 0)
6914 err_code |= ERR_ALERT | ERR_FATAL;
6915 out:
6916 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006917}
6918
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006919/*
6920 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6921 * parsing sessions.
6922 */
6923void cfg_register_keywords(struct cfg_kw_list *kwl)
6924{
6925 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6926}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006928/*
6929 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6930 */
6931void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6932{
6933 LIST_DEL(&kwl->list);
6934 LIST_INIT(&kwl->list);
6935}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006936
6937/*
6938 * Local variables:
6939 * c-indent-level: 8
6940 * c-basic-offset: 8
6941 * End:
6942 */