blob: 4a1ca758ac93a28e3b22aa58ea8e2ab760586ad0 [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 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100665 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
666#ifdef USE_ZLIB
667 if (*args[1]) {
668 global.tune.zlibmemlevel = atoi(args[1]);
669 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
670 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
671 file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675 } else {
676 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
677 file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681#else
682 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
685#endif
686 }
687 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
688#ifdef USE_ZLIB
689 if (*args[1]) {
690 global.tune.zlibwindowsize = atoi(args[1]);
691 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
692 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
693 file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 } else {
698 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
699 file, linenum, args[0]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703#else
704 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707#endif
708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 else if (!strcmp(args[0], "uid")) {
710 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200711 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 }
720 global.uid = atol(args[1]);
721 }
722 else if (!strcmp(args[0], "gid")) {
723 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200724 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733 global.gid = atol(args[1]);
734 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200735 /* user/group name handling */
736 else if (!strcmp(args[0], "user")) {
737 struct passwd *ha_user;
738 if (global.uid != 0) {
739 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200742 }
743 errno = 0;
744 ha_user = getpwnam(args[1]);
745 if (ha_user != NULL) {
746 global.uid = (int)ha_user->pw_uid;
747 }
748 else {
749 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 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200751 }
752 }
753 else if (!strcmp(args[0], "group")) {
754 struct group *ha_group;
755 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200756 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT;
758 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 }
760 errno = 0;
761 ha_group = getgrnam(args[1]);
762 if (ha_group != NULL) {
763 global.gid = (int)ha_group->gr_gid;
764 }
765 else {
766 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 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200768 }
769 }
770 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "nbproc")) {
772 if (global.nbproc != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.nbproc = atol(args[1]);
783 }
784 else if (!strcmp(args[0], "maxconn")) {
785 if (global.maxconn != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 }
795 global.maxconn = atol(args[1]);
796#ifdef SYSTEM_MAXCONN
797 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
798 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);
799 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 }
802#endif /* SYSTEM_MAXCONN */
803 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200804 else if (!strcmp(args[0], "maxsslconn")) {
805#ifdef USE_OPENSSL
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.maxsslconn = atol(args[1]);
812#else
Emeric Brun0914df82012-10-02 18:45:42 +0200813 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200816#endif
817 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200818 else if (!strcmp(args[0], "maxconnrate")) {
819 if (global.cps_lim != 0) {
820 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT;
822 goto out;
823 }
824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
828 }
829 global.cps_lim = atol(args[1]);
830 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100831 else if (!strcmp(args[0], "maxpipes")) {
832 if (global.maxpipes != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT;
835 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100841 }
842 global.maxpipes = atol(args[1]);
843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 else if (!strcmp(args[0], "ulimit-n")) {
845 if (global.rlimit_nofile != 0) {
846 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 if (*(args[1]) == 0) {
851 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200852 err_code |= ERR_ALERT | ERR_FATAL;
853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200854 }
855 global.rlimit_nofile = atol(args[1]);
856 }
857 else if (!strcmp(args[0], "chroot")) {
858 if (global.chroot != NULL) {
859 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT;
861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 if (*(args[1]) == 0) {
864 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200865 err_code |= ERR_ALERT | ERR_FATAL;
866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867 }
868 global.chroot = strdup(args[1]);
869 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200870 else if (!strcmp(args[0], "description")) {
871 int i, len=0;
872 char *d;
873
874 if (!*args[1]) {
875 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880
881 for(i=1; *args[i]; i++)
882 len += strlen(args[i])+1;
883
884 if (global.desc)
885 free(global.desc);
886
887 global.desc = d = (char *)calloc(1, len);
888
889 d += sprintf(d, "%s", args[1]);
890 for(i=2; *args[i]; i++)
891 d += sprintf(d, " %s", args[i]);
892 }
893 else if (!strcmp(args[0], "node")) {
894 int i;
895 char c;
896
897 for (i=0; args[1][i]; i++) {
898 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100899 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
900 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200901 break;
902 }
903
904 if (!i || args[1][i]) {
905 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
906 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
907 file, linenum, args[0]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911
912 if (global.node)
913 free(global.node);
914
915 global.node = strdup(args[1]);
916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 else if (!strcmp(args[0], "pidfile")) {
918 if (global.pidfile != NULL) {
919 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT;
921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 }
923 if (*(args[1]) == 0) {
924 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 global.pidfile = strdup(args[1]);
929 }
Emeric Bruned760922010-10-22 17:59:25 +0200930 else if (!strcmp(args[0], "unix-bind")) {
931 int cur_arg = 1;
932 while (*(args[cur_arg])) {
933 if (!strcmp(args[cur_arg], "prefix")) {
934 if (global.unix_bind.prefix != NULL) {
935 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
936 err_code |= ERR_ALERT;
937 cur_arg += 2;
938 continue;
939 }
940
941 if (*(args[cur_arg+1]) == 0) {
942 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
943 err_code |= ERR_ALERT | ERR_FATAL;
944 goto out;
945 }
946 global.unix_bind.prefix = strdup(args[cur_arg+1]);
947 cur_arg += 2;
948 continue;
949 }
950
951 if (!strcmp(args[cur_arg], "mode")) {
952
953 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
954 cur_arg += 2;
955 continue;
956 }
957
958 if (!strcmp(args[cur_arg], "uid")) {
959
960 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
961 cur_arg += 2;
962 continue;
963 }
964
965 if (!strcmp(args[cur_arg], "gid")) {
966
967 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
968 cur_arg += 2;
969 continue;
970 }
971
972 if (!strcmp(args[cur_arg], "user")) {
973 struct passwd *user;
974
975 user = getpwnam(args[cur_arg + 1]);
976 if (!user) {
977 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
978 file, linenum, args[0], args[cur_arg + 1 ]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982
983 global.unix_bind.ux.uid = user->pw_uid;
984 cur_arg += 2;
985 continue;
986 }
987
988 if (!strcmp(args[cur_arg], "group")) {
989 struct group *group;
990
991 group = getgrnam(args[cur_arg + 1]);
992 if (!group) {
993 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
994 file, linenum, args[0], args[cur_arg + 1 ]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
998
999 global.unix_bind.ux.gid = group->gr_gid;
1000 cur_arg += 2;
1001 continue;
1002 }
1003
Willy Tarreaub48f9582011-09-05 01:17:06 +02001004 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001005 file, linenum, args[0]);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
1008 }
1009 }
William Lallemand0f99e342011-10-12 17:50:54 +02001010 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1011 /* delete previous herited or defined syslog servers */
1012 struct logsrv *back;
1013 struct logsrv *tmp;
1014
1015 if (*(args[1]) != 0) {
1016 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019 }
1020
1021 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1022 LIST_DEL(&tmp->list);
1023 free(tmp);
1024 }
1025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001027 struct logsrv *logsrv;
1028
Willy Tarreaubaaee002006-06-26 02:48:02 +02001029 if (*(args[1]) == 0 || *(args[2]) == 0) {
1030 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001033 }
William Lallemand0f99e342011-10-12 17:50:54 +02001034
1035 logsrv = calloc(1, sizeof(struct logsrv));
1036
1037 logsrv->facility = get_log_facility(args[2]);
1038 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001041 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043
William Lallemand0f99e342011-10-12 17:50:54 +02001044 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001046 logsrv->level = get_log_level(args[3]);
1047 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001050 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
1052 }
1053
William Lallemand0f99e342011-10-12 17:50:54 +02001054 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001055 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001056 logsrv->minlvl = get_log_level(args[4]);
1057 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001058 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001060 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001061 }
1062 }
1063
Robert Tsai81ae1952007-12-05 10:47:29 +01001064 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001065 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001066 if (!sk) {
1067 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001068 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001069 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001070 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001071 goto out;
1072 }
William Lallemand0f99e342011-10-12 17:50:54 +02001073 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001074 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001075 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001076 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001077 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001079 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001080 goto out;
1081 }
William Lallemand0f99e342011-10-12 17:50:54 +02001082 logsrv->addr = *sk;
1083 if (!get_host_port(&logsrv->addr))
1084 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086
William Lallemand0f99e342011-10-12 17:50:54 +02001087 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001088 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001089 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1090 char *name;
1091 int len;
1092
1093 if (global.log_send_hostname != NULL) {
1094 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1095 err_code |= ERR_ALERT;
1096 goto out;
1097 }
1098
1099 if (*(args[1]))
1100 name = args[1];
1101 else
1102 name = hostname;
1103
1104 len = strlen(name);
1105
1106 /* We'll add a space after the name to respect the log format */
1107 free(global.log_send_hostname);
1108 global.log_send_hostname = malloc(len + 2);
1109 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1110 }
Kevinm48936af2010-12-22 16:08:21 +00001111 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1112 if (*(args[1]) == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117 free(global.log_tag);
1118 global.log_tag = strdup(args[1]);
1119 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001120 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1121 if (global.spread_checks != 0) {
1122 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001130 }
1131 global.spread_checks = atol(args[1]);
1132 if (global.spread_checks < 0 || global.spread_checks > 50) {
1133 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001134 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001138 struct cfg_kw_list *kwl;
1139 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001140 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001141
1142 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1143 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1144 if (kwl->kw[index].section != CFG_GLOBAL)
1145 continue;
1146 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001147 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001148 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001149 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001150 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001151 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001152 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001153 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_WARN;
1155 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001156 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001158 }
1159 }
1160 }
1161
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001163 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001165
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001167 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001168 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169}
1170
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001171void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001173 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001174 defproxy.mode = PR_MODE_TCP;
1175 defproxy.state = PR_STNEW;
1176 defproxy.maxconn = cfg_maxpconn;
1177 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001178
1179 defproxy.defsrv.inter = DEF_CHKINTR;
1180 defproxy.defsrv.fastinter = 0;
1181 defproxy.defsrv.downinter = 0;
1182 defproxy.defsrv.rise = DEF_RISETIME;
1183 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001184 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001185 defproxy.defsrv.maxqueue = 0;
1186 defproxy.defsrv.minconn = 0;
1187 defproxy.defsrv.maxconn = 0;
1188 defproxy.defsrv.slowstart = 0;
1189 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1190 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1191 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001192}
1193
Willy Tarreauade5ec42010-01-28 19:33:49 +01001194
1195static int create_cond_regex_rule(const char *file, int line,
1196 struct proxy *px, int dir, int action, int flags,
1197 const char *cmd, const char *reg, const char *repl,
1198 const char **cond_start)
1199{
1200 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001201 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001202 const char *err;
1203 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001204 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001205
1206 if (px == &defproxy) {
1207 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1208 err_code |= ERR_ALERT | ERR_FATAL;
1209 goto err;
1210 }
1211
1212 if (*reg == 0) {
1213 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto err;
1216 }
1217
1218 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1219 err_code |= ERR_WARN;
1220
Willy Tarreau5321c422010-01-28 20:35:13 +01001221 if (cond_start &&
1222 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001223 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1224 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1225 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto err;
1228 }
1229 }
1230 else if (cond_start && **cond_start) {
1231 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1232 file, line, cmd, *cond_start);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto err;
1235 }
1236
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001237 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001238 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001239 else
1240 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001241
Willy Tarreauade5ec42010-01-28 19:33:49 +01001242 preg = calloc(1, sizeof(regex_t));
1243 if (!preg) {
1244 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1245 err_code = ERR_ALERT | ERR_FATAL;
1246 goto err;
1247 }
1248
1249 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1250 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1251 err_code = ERR_ALERT | ERR_FATAL;
1252 goto err;
1253 }
1254
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001255 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001256 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001257 if (repl && err) {
1258 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1259 file, line, cmd, *err);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto err;
1262 }
1263
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001264 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001265 err_code |= ERR_WARN;
1266
Willy Tarreauf4068b62012-05-08 17:37:49 +02001267 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001268 return err_code;
1269 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001270 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001271 free(preg);
1272 return err_code;
1273}
1274
Willy Tarreaubaaee002006-06-26 02:48:02 +02001275/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001276 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001277 * Returns the error code, 0 if OK, or any combination of :
1278 * - ERR_ABORT: must abort ASAP
1279 * - ERR_FATAL: we can continue parsing but not start the service
1280 * - ERR_WARN: a warning has been emitted
1281 * - ERR_ALERT: an alert has been emitted
1282 * Only the two first ones can stop processing, the two others are just
1283 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001285int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1286{
1287 static struct peers *curpeers = NULL;
1288 struct peer *newpeer = NULL;
1289 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001290 struct bind_conf *bind_conf;
1291 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001292 int err_code = 0;
1293
1294 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1295
1296 err = invalid_char(args[1]);
1297 if (err) {
1298 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1299 file, linenum, *err, args[0], args[1]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 }
1302
1303 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1304 /*
1305 * If there are two proxies with the same name only following
1306 * combinations are allowed:
1307 */
1308 if (strcmp(curpeers->id, args[1]) == 0) {
1309 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1310 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1311 err_code |= ERR_WARN;
1312 }
1313 }
1314
1315 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1317 err_code |= ERR_ALERT | ERR_ABORT;
1318 goto out;
1319 }
1320
1321 curpeers->next = peers;
1322 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001323 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001324 curpeers->conf.line = linenum;
1325 curpeers->last_change = now.tv_sec;
1326 curpeers->id = strdup(args[1]);
1327 }
1328 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1329 char *rport, *raddr;
1330 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001331 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001332 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001333
1334 if (!*args[2]) {
1335 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1336 file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
1340
1341 err = invalid_char(args[1]);
1342 if (err) {
1343 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1344 file, linenum, *err, args[1]);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348
1349 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1350 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1351 err_code |= ERR_ALERT | ERR_ABORT;
1352 goto out;
1353 }
1354
1355 /* the peers are linked backwards first */
1356 curpeers->count++;
1357 newpeer->next = curpeers->remote;
1358 curpeers->remote = newpeer;
1359 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001360 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001361 newpeer->conf.line = linenum;
1362
1363 newpeer->last_change = now.tv_sec;
1364 newpeer->id = strdup(args[1]);
1365
1366 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001367 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001368 if (rport) {
1369 *rport++ = 0;
1370 realport = atol(rport);
1371 }
1372 if (!realport) {
1373 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376 }
1377
Willy Tarreaufab5a432011-03-04 15:31:53 +01001378 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001379 free(raddr);
1380 if (!sk) {
1381 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
1384 }
1385 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001386 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001387 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001388 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001389
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001390 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001391 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1392 file, linenum, newpeer->addr.ss_family, args[2]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
1396
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001397 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001398
1399 if (strcmp(newpeer->id, localpeer) == 0) {
1400 /* Current is local peer, it define a frontend */
1401 newpeer->local = 1;
1402
1403 if (!curpeers->peers_fe) {
1404 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1406 err_code |= ERR_ALERT | ERR_ABORT;
1407 goto out;
1408 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001409
Willy Tarreau237250c2011-07-29 01:49:03 +02001410 init_new_proxy(curpeers->peers_fe);
1411 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001412
1413 curpeers->peers_fe->last_change = now.tv_sec;
1414 curpeers->peers_fe->id = strdup(args[1]);
1415 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001416 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001417 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1418 curpeers->peers_fe->timeout.connect = 5000;
1419 curpeers->peers_fe->accept = peer_accept;
1420 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001421
1422 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1423
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001424 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1425 if (err_msg && *err_msg) {
1426 indent_msg(&err_msg, 2);
1427 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1428 }
1429 else
1430 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1431 file, linenum, args[0], args[1], args[2]);
1432 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001433 err_code |= ERR_FATAL;
1434 goto out;
1435 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001436
1437 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1438 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1439 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1440 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1441 l->accept = session_accept;
1442 l->handler = process_session;
1443 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1444 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1445 global.maxsock += l->maxconn;
1446 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001447 }
1448 }
1449 } /* neither "peer" nor "peers" */
1450 else if (*args[0] != 0) {
1451 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
1454 }
1455
1456out:
1457 return err_code;
1458}
1459
1460
Willy Tarreau3842f002009-06-14 11:39:52 +02001461int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462{
1463 static struct proxy *curproxy = NULL;
1464 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001465 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001466 int rc;
1467 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001468 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001469 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001470 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001471 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001472 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (!strcmp(args[0], "listen"))
1475 rc = PR_CAP_LISTEN;
1476 else if (!strcmp(args[0], "frontend"))
1477 rc = PR_CAP_FE | PR_CAP_RS;
1478 else if (!strcmp(args[0], "backend"))
1479 rc = PR_CAP_BE | PR_CAP_RS;
1480 else if (!strcmp(args[0], "ruleset"))
1481 rc = PR_CAP_RS;
1482 else
1483 rc = PR_CAP_NONE;
1484
1485 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 if (!*args[1]) {
1487 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1488 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1489 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001490 err_code |= ERR_ALERT | ERR_ABORT;
1491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001493
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001494 err = invalid_char(args[1]);
1495 if (err) {
1496 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1497 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001499 }
1500
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001501 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1502 /*
1503 * If there are two proxies with the same name only following
1504 * combinations are allowed:
1505 *
1506 * listen backend frontend ruleset
1507 * listen - - - -
1508 * backend - - OK -
1509 * frontend - OK - -
1510 * ruleset - - - -
1511 */
1512
1513 if (!strcmp(curproxy->id, args[1]) &&
1514 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1515 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001516 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1517 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1518 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001519 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001520 }
1521 }
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1524 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001525 err_code |= ERR_ALERT | ERR_ABORT;
1526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001528
Willy Tarreau97cb7802010-01-03 20:23:58 +01001529 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 curproxy->next = proxy;
1531 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001532 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001533 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001534 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537
1538 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001539 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001540 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001541 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001542
Willy Tarreau4348fad2012-09-20 16:48:07 +02001543 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1544
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001545 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1546 if (err_msg && *err_msg) {
1547 indent_msg(&err_msg, 2);
1548 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1549 }
1550 else
1551 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1552 file, linenum, args[0], args[1], args[2]);
1553 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001554 err_code |= ERR_FATAL;
1555 goto out;
1556 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001557
Willy Tarreau4348fad2012-09-20 16:48:07 +02001558 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001559 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561 }
1562
1563 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001564 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001565 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001566
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001569 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001570 curproxy->no_options = defproxy.no_options;
1571 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001572 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001573 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001574 curproxy->except_net = defproxy.except_net;
1575 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001576 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001577 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001579 if (defproxy.fwdfor_hdr_len) {
1580 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1581 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1582 }
1583
Willy Tarreaub86db342009-11-30 11:50:16 +01001584 if (defproxy.orgto_hdr_len) {
1585 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1586 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1587 }
1588
Mark Lamourinec2247f02012-01-04 13:02:01 -05001589 if (defproxy.server_id_hdr_len) {
1590 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1591 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1592 }
1593
Willy Tarreau977b8e42006-12-29 14:19:17 +01001594 if (curproxy->cap & PR_CAP_FE) {
1595 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001596 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001597 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001598
1599 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001600 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1601 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001602
1603 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605
Willy Tarreau977b8e42006-12-29 14:19:17 +01001606 if (curproxy->cap & PR_CAP_BE) {
1607 curproxy->fullconn = defproxy.fullconn;
1608 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001610 if (defproxy.check_req) {
1611 curproxy->check_req = calloc(1, defproxy.check_len);
1612 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1613 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001614 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001616 if (defproxy.expect_str) {
1617 curproxy->expect_str = strdup(defproxy.expect_str);
1618 if (defproxy.expect_regex) {
1619 /* note: this regex is known to be valid */
1620 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1621 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1622 }
1623 }
1624
Willy Tarreau67402132012-05-31 20:40:20 +02001625 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001626 if (defproxy.cookie_name)
1627 curproxy->cookie_name = strdup(defproxy.cookie_name);
1628 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001629 if (defproxy.cookie_domain)
1630 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001631
Willy Tarreau31936852010-10-06 16:59:56 +02001632 if (defproxy.cookie_maxidle)
1633 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1634
1635 if (defproxy.cookie_maxlife)
1636 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1637
Emeric Brun647caf12009-06-30 17:57:00 +02001638 if (defproxy.rdp_cookie_name)
1639 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1640 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1641
Willy Tarreau01732802007-11-01 22:48:15 +01001642 if (defproxy.url_param_name)
1643 curproxy->url_param_name = strdup(defproxy.url_param_name);
1644 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001645
Benoitaffb4812009-03-25 13:02:10 +01001646 if (defproxy.hh_name)
1647 curproxy->hh_name = strdup(defproxy.hh_name);
1648 curproxy->hh_len = defproxy.hh_len;
1649 curproxy->hh_match_domain = defproxy.hh_match_domain;
1650
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001651 if (defproxy.iface_name)
1652 curproxy->iface_name = strdup(defproxy.iface_name);
1653 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001656 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001657 if (defproxy.capture_name)
1658 curproxy->capture_name = strdup(defproxy.capture_name);
1659 curproxy->capture_namelen = defproxy.capture_namelen;
1660 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662
Willy Tarreau977b8e42006-12-29 14:19:17 +01001663 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001664 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001665 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001666 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001667 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001668 curproxy->uri_auth = defproxy.uri_auth;
1669 curproxy->mon_net = defproxy.mon_net;
1670 curproxy->mon_mask = defproxy.mon_mask;
1671 if (defproxy.monitor_uri)
1672 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1673 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001674 if (defproxy.defbe.name)
1675 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001676
1677 /* get either a pointer to the logformat string or a copy of it */
1678 curproxy->logformat_string = defproxy.logformat_string;
1679 if (curproxy->logformat_string &&
1680 curproxy->logformat_string != default_http_log_format &&
1681 curproxy->logformat_string != default_tcp_log_format &&
1682 curproxy->logformat_string != clf_http_log_format)
1683 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001684 }
1685
1686 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001687 curproxy->timeout.connect = defproxy.timeout.connect;
1688 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001689 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001690 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001691 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001692 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001693 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001694 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001695 curproxy->source_addr = defproxy.source_addr;
1696 }
1697
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001699
1700 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001701 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001702 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001703 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001704 LIST_INIT(&node->list);
1705 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1706 }
1707
Willy Tarreau196729e2012-05-31 19:30:26 +02001708 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1709 if (curproxy->uniqueid_format_string)
1710 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001711
1712 /* copy default header unique id */
1713 if (defproxy.header_unique_id)
1714 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1715
William Lallemand82fe75c2012-10-23 10:25:10 +02001716 /* default compression options */
1717 if (defproxy.comp != NULL) {
1718 curproxy->comp = calloc(1, sizeof(struct comp));
1719 curproxy->comp->algos = defproxy.comp->algos;
1720 curproxy->comp->types = defproxy.comp->types;
1721 }
1722
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001724 curproxy->conf.used_listener_id = EB_ROOT;
1725 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001726
Willy Tarreau93893792009-07-23 13:19:11 +02001727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 }
1729 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1730 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001731 /* FIXME-20070101: we should do this too at the end of the
1732 * config parsing to free all default values.
1733 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001734 free(defproxy.check_req);
1735 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001736 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001737 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001738 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001739 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001740 free(defproxy.capture_name);
1741 free(defproxy.monitor_uri);
1742 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001743 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001744 free(defproxy.fwdfor_hdr_name);
1745 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001746 free(defproxy.orgto_hdr_name);
1747 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001748 free(defproxy.server_id_hdr_name);
1749 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001750 free(defproxy.expect_str);
1751 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001752
Willy Tarreau39b06652012-06-01 10:58:06 +02001753 if (defproxy.logformat_string != default_http_log_format &&
1754 defproxy.logformat_string != default_tcp_log_format &&
1755 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001756 free(defproxy.logformat_string);
1757
1758 free(defproxy.uniqueid_format_string);
1759
Willy Tarreaua534fea2008-08-03 12:19:50 +02001760 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001761 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001762
Willy Tarreaubaaee002006-06-26 02:48:02 +02001763 /* we cannot free uri_auth because it might already be used */
1764 init_default_instance();
1765 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 }
1769 else if (curproxy == NULL) {
1770 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 }
1774
Willy Tarreau977b8e42006-12-29 14:19:17 +01001775
1776 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001778 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001779 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001780 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001781
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782 if (curproxy == &defproxy) {
1783 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001788 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789
Emeric Bruned760922010-10-22 17:59:25 +02001790 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001791 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001796
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001797 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001798 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001799
1800 /* NOTE: the following line might create several listeners if there
1801 * are comma-separated IPs or port ranges. So all further processing
1802 * will have to be applied to all listeners created after last_listen.
1803 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001804 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1805 if (err_msg && *err_msg) {
1806 indent_msg(&err_msg, 2);
1807 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1808 }
1809 else
1810 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1811 file, linenum, args[0], args[1]);
1812 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001816
Willy Tarreau4348fad2012-09-20 16:48:07 +02001817 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1818 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001819 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001820 }
1821
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001822 cur_arg = 2;
1823 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001824 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001825 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001826 char *err;
1827
Willy Tarreau26982662012-09-12 23:17:10 +02001828 kw = bind_find_kw(args[cur_arg]);
1829 if (kw) {
1830 char *err = NULL;
1831 int code;
1832
1833 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001834 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1835 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001836 cur_arg += 1 + kw->skip ;
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840
Willy Tarreau4348fad2012-09-20 16:48:07 +02001841 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001842 err_code |= code;
1843
1844 if (code) {
1845 if (err && *err) {
1846 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001847 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001848 }
1849 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001850 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1851 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001852 if (code & ERR_FATAL) {
1853 free(err);
1854 cur_arg += 1 + kw->skip;
1855 goto out;
1856 }
1857 }
1858 free(err);
1859 cur_arg += 1 + kw->skip;
1860 continue;
1861 }
1862
Willy Tarreau8638f482012-09-18 18:01:17 +02001863 err = NULL;
1864 if (!bind_dumped) {
1865 bind_dump_kws(&err);
1866 indent_msg(&err, 4);
1867 bind_dumped = 1;
1868 }
1869
1870 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1871 file, linenum, args[0], args[1], args[cur_arg],
1872 err ? " Registered keywords :" : "", err ? err : "");
1873 free(err);
1874
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001877 }
Willy Tarreau93893792009-07-23 13:19:11 +02001878 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001879 }
1880 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1881 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1882 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1883 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 /* flush useless bits */
1891 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001894 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897
Willy Tarreau1c47f852006-07-09 08:22:27 +02001898 if (!*args[1]) {
1899 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001903 }
1904
Willy Tarreaua534fea2008-08-03 12:19:50 +02001905 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001906 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001907 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001908 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001909 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1910
Willy Tarreau93893792009-07-23 13:19:11 +02001911 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1914 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1915 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1916 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1917 else {
1918 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 }
1922 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001923 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001924 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001925
1926 if (curproxy == &defproxy) {
1927 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001931 }
1932
1933 if (!*args[1]) {
1934 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1935 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001938 }
1939
1940 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001941 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001942
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001943 if (curproxy->uuid <= 0) {
1944 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001945 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948 }
1949
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001950 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1951 if (node) {
1952 struct proxy *target = container_of(node, struct proxy, conf.id);
1953 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1954 file, linenum, proxy_type_str(curproxy), curproxy->id,
1955 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
1958 }
1959 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001960 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001961 else if (!strcmp(args[0], "description")) {
1962 int i, len=0;
1963 char *d;
1964
Cyril Bonté99ed3272010-01-24 23:29:44 +01001965 if (curproxy == &defproxy) {
1966 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1967 file, linenum, args[0]);
1968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
1970 }
1971
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001972 if (!*args[1]) {
1973 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1974 file, linenum, args[0]);
1975 return -1;
1976 }
1977
1978 for(i=1; *args[i]; i++)
1979 len += strlen(args[i])+1;
1980
1981 d = (char *)calloc(1, len);
1982 curproxy->desc = d;
1983
1984 d += sprintf(d, "%s", args[1]);
1985 for(i=2; *args[i]; i++)
1986 d += sprintf(d, " %s", args[i]);
1987
1988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1990 curproxy->state = PR_STSTOPPED;
1991 }
1992 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1993 curproxy->state = PR_STNEW;
1994 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001995 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1996 int cur_arg = 1;
1997 unsigned int set = 0;
1998
1999 while (*args[cur_arg]) {
2000 int u;
2001 if (strcmp(args[cur_arg], "all") == 0) {
2002 set = 0;
2003 break;
2004 }
2005 else if (strcmp(args[cur_arg], "odd") == 0) {
2006 set |= 0x55555555;
2007 }
2008 else if (strcmp(args[cur_arg], "even") == 0) {
2009 set |= 0xAAAAAAAA;
2010 }
2011 else {
2012 u = str2uic(args[cur_arg]);
2013 if (u < 1 || u > 32) {
2014 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002018 }
2019 if (u > global.nbproc) {
2020 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2021 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002022 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002023 }
2024 set |= 1 << (u - 1);
2025 }
2026 cur_arg++;
2027 }
2028 curproxy->bind_proc = set;
2029 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002030 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002031 if (curproxy == &defproxy) {
2032 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002035 }
2036
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002037 err = invalid_char(args[1]);
2038 if (err) {
2039 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2040 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002042 }
2043
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002044 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2045 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2046 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002049 }
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2052 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 if (*(args[1]) == 0) {
2058 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2059 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002063
Willy Tarreau67402132012-05-31 20:40:20 +02002064 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002065 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002066 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002067 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 curproxy->cookie_name = strdup(args[1]);
2069 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 cur_arg = 2;
2072 while (*(args[cur_arg])) {
2073 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002074 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 }
2076 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002077 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 }
2079 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002080 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 }
2082 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002083 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 }
2085 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002086 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002088 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002089 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002090 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002092 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002094 else if (!strcmp(args[cur_arg], "httponly")) {
2095 curproxy->ck_opts |= PR_CK_HTTPONLY;
2096 }
2097 else if (!strcmp(args[cur_arg], "secure")) {
2098 curproxy->ck_opts |= PR_CK_SECURE;
2099 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002100 else if (!strcmp(args[cur_arg], "domain")) {
2101 if (!*args[cur_arg + 1]) {
2102 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2103 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002106 }
2107
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002108 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002109 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002110 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2111 " dots nor does not start with a dot."
2112 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002114 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002115 }
2116
2117 err = invalid_domainchar(args[cur_arg + 1]);
2118 if (err) {
2119 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2120 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002123 }
2124
Willy Tarreau68a897b2009-12-03 23:28:34 +01002125 if (!curproxy->cookie_domain) {
2126 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2127 } else {
2128 /* one domain was already specified, add another one by
2129 * building the string which will be returned along with
2130 * the cookie.
2131 */
2132 char *new_ptr;
2133 int new_len = strlen(curproxy->cookie_domain) +
2134 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2135 new_ptr = malloc(new_len);
2136 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2137 free(curproxy->cookie_domain);
2138 curproxy->cookie_domain = new_ptr;
2139 }
Willy Tarreau31936852010-10-06 16:59:56 +02002140 cur_arg++;
2141 }
2142 else if (!strcmp(args[cur_arg], "maxidle")) {
2143 unsigned int maxidle;
2144 const char *res;
2145
2146 if (!*args[cur_arg + 1]) {
2147 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2148 file, linenum, args[cur_arg]);
2149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
2151 }
2152
2153 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2154 if (res) {
2155 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2156 file, linenum, *res, args[cur_arg]);
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160 curproxy->cookie_maxidle = maxidle;
2161 cur_arg++;
2162 }
2163 else if (!strcmp(args[cur_arg], "maxlife")) {
2164 unsigned int maxlife;
2165 const char *res;
2166
2167 if (!*args[cur_arg + 1]) {
2168 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2169 file, linenum, args[cur_arg]);
2170 err_code |= ERR_ALERT | ERR_FATAL;
2171 goto out;
2172 }
2173
2174 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2175 if (res) {
2176 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2177 file, linenum, *res, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002182 cur_arg++;
2183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002185 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 +02002186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
2190 cur_arg++;
2191 }
Willy Tarreau67402132012-05-31 20:40:20 +02002192 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2194 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197
Willy Tarreau67402132012-05-31 20:40:20 +02002198 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002203
Willy Tarreau67402132012-05-31 20:40:20 +02002204 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002205 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2206 file, linenum);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002210 else if (!strcmp(args[0], "persist")) { /* persist */
2211 if (*(args[1]) == 0) {
2212 Alert("parsing [%s:%d] : missing persist method.\n",
2213 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002216 }
2217
2218 if (!strncmp(args[1], "rdp-cookie", 10)) {
2219 curproxy->options2 |= PR_O2_RDPC_PRST;
2220
Emeric Brunb982a3d2010-01-04 15:45:53 +01002221 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002222 const char *beg, *end;
2223
2224 beg = args[1] + 11;
2225 end = strchr(beg, ')');
2226
2227 if (!end || end == beg) {
2228 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002232 }
2233
2234 free(curproxy->rdp_cookie_name);
2235 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2236 curproxy->rdp_cookie_len = end-beg;
2237 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002238 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002239 free(curproxy->rdp_cookie_name);
2240 curproxy->rdp_cookie_name = strdup("msts");
2241 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2242 }
2243 else { /* syntax */
2244 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2245 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002248 }
2249 }
2250 else {
2251 Alert("parsing [%s:%d] : unknown persist method.\n",
2252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002255 }
2256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002257 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002258 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002260 if (curproxy == &defproxy) {
2261 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
2264 }
2265
Willy Tarreau977b8e42006-12-29 14:19:17 +01002266 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002268
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002270 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
2275 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002276 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 curproxy->appsession_name = strdup(args[1]);
2278 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2279 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002280 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2281 if (err) {
2282 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2283 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002286 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002287 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002288
Willy Tarreau51041c72007-09-09 21:56:53 +02002289 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2290 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_ABORT;
2292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002294
2295 cur_arg = 6;
2296 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002297 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2298 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002299 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002300 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002301 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002302 } else if (!strcmp(args[cur_arg], "prefix")) {
2303 curproxy->options2 |= PR_O2_AS_PFX;
2304 } else if (!strcmp(args[cur_arg], "mode")) {
2305 if (!*args[cur_arg + 1]) {
2306 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2307 file, linenum, args[0], args[cur_arg]);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311
2312 cur_arg++;
2313 if (!strcmp(args[cur_arg], "query-string")) {
2314 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2315 curproxy->options2 |= PR_O2_AS_M_QS;
2316 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2317 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2318 curproxy->options2 |= PR_O2_AS_M_PP;
2319 } else {
2320 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
2323 }
2324 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002325 cur_arg++;
2326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 } /* Url App Session */
2328 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002329 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002331
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002333 if (curproxy == &defproxy) {
2334 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (*(args[4]) == 0) {
2340 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->capture_name = strdup(args[2]);
2347 curproxy->capture_namelen = strlen(curproxy->capture_name);
2348 curproxy->capture_len = atol(args[4]);
2349 if (curproxy->capture_len >= CAPTURE_LEN) {
2350 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2351 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 curproxy->capture_len = CAPTURE_LEN - 1;
2354 }
2355 curproxy->to_log |= LW_COOKIE;
2356 }
2357 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2358 struct cap_hdr *hdr;
2359
2360 if (curproxy == &defproxy) {
2361 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 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365
2366 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2367 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2368 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
2372
2373 hdr = calloc(sizeof(struct cap_hdr), 1);
2374 hdr->next = curproxy->req_cap;
2375 hdr->name = strdup(args[3]);
2376 hdr->namelen = strlen(args[3]);
2377 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002378 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 hdr->index = curproxy->nb_req_cap++;
2380 curproxy->req_cap = hdr;
2381 curproxy->to_log |= LW_REQHDR;
2382 }
2383 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2384 struct cap_hdr *hdr;
2385
2386 if (curproxy == &defproxy) {
2387 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 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391
2392 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2393 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2394 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398 hdr = calloc(sizeof(struct cap_hdr), 1);
2399 hdr->next = curproxy->rsp_cap;
2400 hdr->name = strdup(args[3]);
2401 hdr->namelen = strlen(args[3]);
2402 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002403 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 hdr->index = curproxy->nb_rsp_cap++;
2405 curproxy->rsp_cap = hdr;
2406 curproxy->to_log |= LW_RSPHDR;
2407 }
2408 else {
2409 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2410 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 }
2414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002416 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002418
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 if (*(args[1]) == 0) {
2420 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2421 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 curproxy->conn_retries = atol(args[1]);
2426 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002427 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002428 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002429
2430 if (curproxy == &defproxy) {
2431 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
Willy Tarreauff011f22011-01-06 17:51:27 +01002436 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 +01002437 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2438 file, linenum, args[0]);
2439 err_code |= ERR_WARN;
2440 }
2441
Willy Tarreauff011f22011-01-06 17:51:27 +01002442 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002443
Willy Tarreauff011f22011-01-06 17:51:27 +01002444 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002445 err_code |= ERR_ALERT | ERR_ABORT;
2446 goto out;
2447 }
2448
Willy Tarreauff011f22011-01-06 17:51:27 +01002449 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2450 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002451 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002452 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2453 /* set the header name and length into the proxy structure */
2454 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2455 err_code |= ERR_WARN;
2456
2457 if (!*args[1]) {
2458 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2459 file, linenum, args[0]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463
2464 /* set the desired header name */
2465 free(curproxy->server_id_hdr_name);
2466 curproxy->server_id_hdr_name = strdup(args[1]);
2467 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2468 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002469 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002470 if (curproxy == &defproxy) {
2471 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002474 }
2475
Willy Tarreauef6494c2010-01-28 17:12:36 +01002476 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002477 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2478 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002481 }
2482
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002483 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2484 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2485 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002488 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002489
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002490 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002491 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002492 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002493 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002494 struct redirect_rule *rule;
2495 int cur_arg;
2496 int type = REDIRECT_TYPE_NONE;
2497 int code = 302;
2498 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002499 char *cookie = NULL;
2500 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002501 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002502
Cyril Bonté99ed3272010-01-24 23:29:44 +01002503 if (curproxy == &defproxy) {
2504 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
2507 }
2508
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002509 cur_arg = 1;
2510 while (*(args[cur_arg])) {
2511 if (!strcmp(args[cur_arg], "location")) {
2512 if (!*args[cur_arg + 1]) {
2513 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2514 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002517 }
2518
2519 type = REDIRECT_TYPE_LOCATION;
2520 cur_arg++;
2521 destination = args[cur_arg];
2522 }
2523 else if (!strcmp(args[cur_arg], "prefix")) {
2524 if (!*args[cur_arg + 1]) {
2525 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2526 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002529 }
2530
2531 type = REDIRECT_TYPE_PREFIX;
2532 cur_arg++;
2533 destination = args[cur_arg];
2534 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002535 else if (!strcmp(args[cur_arg], "scheme")) {
2536 if (!*args[cur_arg + 1]) {
2537 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2538 file, linenum, args[0], args[cur_arg]);
2539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
2541 }
2542
2543 type = REDIRECT_TYPE_SCHEME;
2544 cur_arg++;
2545 destination = args[cur_arg];
2546 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002547 else if (!strcmp(args[cur_arg], "set-cookie")) {
2548 if (!*args[cur_arg + 1]) {
2549 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2550 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002553 }
2554
2555 cur_arg++;
2556 cookie = args[cur_arg];
2557 cookie_set = 1;
2558 }
2559 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2560 if (!*args[cur_arg + 1]) {
2561 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2562 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 Tarreau0140f252008-11-19 21:07:09 +01002565 }
2566
2567 cur_arg++;
2568 cookie = args[cur_arg];
2569 cookie_set = 0;
2570 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002571 else if (!strcmp(args[cur_arg],"code")) {
2572 if (!*args[cur_arg + 1]) {
2573 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 }
2578 cur_arg++;
2579 code = atol(args[cur_arg]);
2580 if (code < 301 || code > 303) {
2581 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2582 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002585 }
2586 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002587 else if (!strcmp(args[cur_arg],"drop-query")) {
2588 flags |= REDIRECT_FLAG_DROP_QS;
2589 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002590 else if (!strcmp(args[cur_arg],"append-slash")) {
2591 flags |= REDIRECT_FLAG_APPEND_SLASH;
2592 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002593 else if (strcmp(args[cur_arg], "if") == 0 ||
2594 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002595 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002596 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002597 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2598 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002602 break;
2603 }
2604 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002605 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 +02002606 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002609 }
2610 cur_arg++;
2611 }
2612
2613 if (type == REDIRECT_TYPE_NONE) {
2614 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2615 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002618 }
2619
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002620 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2621 rule->cond = cond;
2622 rule->rdr_str = strdup(destination);
2623 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002624 if (cookie) {
2625 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002626 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002627 */
2628 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002629 if (cookie_set) {
2630 rule->cookie_str = malloc(rule->cookie_len + 10);
2631 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2632 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2633 rule->cookie_len += 9;
2634 } else {
2635 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002636 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002637 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2638 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002639 }
2640 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002641 rule->type = type;
2642 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002643 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002644 LIST_INIT(&rule->list);
2645 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002646 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2647 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002649 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 struct switching_rule *rule;
2651
Willy Tarreaub099aca2008-10-12 17:26:37 +02002652 if (curproxy == &defproxy) {
2653 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002656 }
2657
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002660
2661 if (*(args[1]) == 0) {
2662 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002665 }
2666
Willy Tarreauef6494c2010-01-28 17:12:36 +01002667 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002672 }
2673
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002674 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2675 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2676 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002679 }
2680
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002681 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002682
Willy Tarreau55ea7572007-06-17 19:56:27 +02002683 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2684 rule->cond = cond;
2685 rule->be.name = strdup(args[1]);
2686 LIST_INIT(&rule->list);
2687 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2688 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002689 else if (strcmp(args[0], "use-server") == 0) {
2690 struct server_rule *rule;
2691
2692 if (curproxy == &defproxy) {
2693 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697
2698 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2699 err_code |= ERR_WARN;
2700
2701 if (*(args[1]) == 0) {
2702 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706
2707 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2708 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2709 file, linenum, args[0]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002714 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2715 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2716 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720
2721 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2722
2723 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2724 rule->cond = cond;
2725 rule->srv.name = strdup(args[1]);
2726 LIST_INIT(&rule->list);
2727 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2728 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2729 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002730 else if ((!strcmp(args[0], "force-persist")) ||
2731 (!strcmp(args[0], "ignore-persist"))) {
2732 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002733
2734 if (curproxy == &defproxy) {
2735 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739
2740 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2741 err_code |= ERR_WARN;
2742
Willy Tarreauef6494c2010-01-28 17:12:36 +01002743 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002744 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2745 file, linenum, args[0]);
2746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002750 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2751 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2752 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
2756
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002757 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002758
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002759 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002760 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002761 if (!strcmp(args[0], "force-persist")) {
2762 rule->type = PERSIST_TYPE_FORCE;
2763 } else {
2764 rule->type = PERSIST_TYPE_IGNORE;
2765 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002766 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002767 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002768 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002769 else if (!strcmp(args[0], "stick-table")) {
2770 int myidx = 1;
2771
Emeric Brun32da3c42010-09-23 18:39:19 +02002772 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002773 curproxy->table.type = (unsigned int)-1;
2774 while (*args[myidx]) {
2775 const char *err;
2776
2777 if (strcmp(args[myidx], "size") == 0) {
2778 myidx++;
2779 if (!*(args[myidx])) {
2780 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2781 file, linenum, args[myidx-1]);
2782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2786 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2787 file, linenum, *err, args[myidx-1]);
2788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002791 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002792 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002793 else if (strcmp(args[myidx], "peers") == 0) {
2794 myidx++;
2795 if (!*(args[myidx])) {
2796 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2797 file, linenum, args[myidx-1]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801 curproxy->table.peers.name = strdup(args[myidx++]);
2802 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002803 else if (strcmp(args[myidx], "expire") == 0) {
2804 myidx++;
2805 if (!*(args[myidx])) {
2806 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2807 file, linenum, args[myidx-1]);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
2810 }
2811 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2812 if (err) {
2813 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2814 file, linenum, *err, args[myidx-1]);
2815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
2817 }
2818 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002819 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 }
2821 else if (strcmp(args[myidx], "nopurge") == 0) {
2822 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002823 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002824 }
2825 else if (strcmp(args[myidx], "type") == 0) {
2826 myidx++;
2827 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2828 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2829 file, linenum, args[myidx]);
2830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
2832 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002833 /* myidx already points to next arg */
2834 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002835 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002836 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002837 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002838
2839 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002840 nw = args[myidx];
2841 while (*nw) {
2842 /* the "store" keyword supports a comma-separated list */
2843 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002844 sa = NULL; /* store arg */
2845 while (*nw && *nw != ',') {
2846 if (*nw == '(') {
2847 *nw = 0;
2848 sa = ++nw;
2849 while (*nw != ')') {
2850 if (!*nw) {
2851 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2852 file, linenum, args[0], cw);
2853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
2855 }
2856 nw++;
2857 }
2858 *nw = '\0';
2859 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002860 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002861 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002862 if (*nw)
2863 *nw++ = '\0';
2864 type = stktable_get_data_type(cw);
2865 if (type < 0) {
2866 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2867 file, linenum, args[0], cw);
2868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
Willy Tarreauac782882010-06-20 10:41:54 +02002871
2872 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2873 switch (err) {
2874 case PE_NONE: break;
2875 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002876 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2877 file, linenum, args[0], cw);
2878 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002879 break;
2880
2881 case PE_ARG_MISSING:
2882 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2883 file, linenum, args[0], cw);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886
2887 case PE_ARG_NOT_USED:
2888 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2889 file, linenum, args[0], cw);
2890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892
2893 default:
2894 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2895 file, linenum, args[0], cw);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002898 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002899 }
2900 myidx++;
2901 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002902 else {
2903 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2904 file, linenum, args[myidx]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002907 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 }
2909
2910 if (!curproxy->table.size) {
2911 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2912 file, linenum);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (curproxy->table.type == (unsigned int)-1) {
2918 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2919 file, linenum);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 }
2924 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002926 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002927 int myidx = 0;
2928 const char *name = NULL;
2929 int flags;
2930
2931 if (curproxy == &defproxy) {
2932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
2937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2938 err_code |= ERR_WARN;
2939 goto out;
2940 }
2941
2942 myidx++;
2943 if ((strcmp(args[myidx], "store") == 0) ||
2944 (strcmp(args[myidx], "store-request") == 0)) {
2945 myidx++;
2946 flags = STK_IS_STORE;
2947 }
2948 else if (strcmp(args[myidx], "store-response") == 0) {
2949 myidx++;
2950 flags = STK_IS_STORE | STK_ON_RSP;
2951 }
2952 else if (strcmp(args[myidx], "match") == 0) {
2953 myidx++;
2954 flags = STK_IS_MATCH;
2955 }
2956 else if (strcmp(args[myidx], "on") == 0) {
2957 myidx++;
2958 flags = STK_IS_MATCH | STK_IS_STORE;
2959 }
2960 else {
2961 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (*(args[myidx]) == 0) {
2967 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002972 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002973 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002974 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
2977 }
2978
2979 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002980 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002981 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2982 file, linenum, args[0], expr->fetch->kw);
2983 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002984 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002985 goto out;
2986 }
2987 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002988 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002989 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2990 file, linenum, args[0], expr->fetch->kw);
2991 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002992 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002993 goto out;
2994 }
2995 }
2996
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02002997 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
2998 if (expr->fetch->cap & SMP_CAP_L7)
2999 curproxy->acl_requires |= ACL_USE_L7_ANY;
3000
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 if (strcmp(args[myidx], "table") == 0) {
3002 myidx++;
3003 name = args[myidx++];
3004 }
3005
Willy Tarreauef6494c2010-01-28 17:12:36 +01003006 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003007 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3008 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3009 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003011 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003012 goto out;
3013 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003015 else if (*(args[myidx])) {
3016 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3017 file, linenum, args[0], args[myidx]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003019 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003020 goto out;
3021 }
Emeric Brun97679e72010-09-23 17:56:44 +02003022 if (flags & STK_ON_RSP)
3023 err_code |= warnif_cond_requires_req(cond, file, linenum);
3024 else
3025 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003026
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3028 rule->cond = cond;
3029 rule->expr = expr;
3030 rule->flags = flags;
3031 rule->table.name = name ? strdup(name) : NULL;
3032 LIST_INIT(&rule->list);
3033 if (flags & STK_ON_RSP)
3034 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3035 else
3036 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003039 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003041
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3043 curproxy->uri_auth = NULL; /* we must detach from the default config */
3044
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003045 if (!*args[1]) {
3046 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003047 } else if (!strcmp(args[1], "admin")) {
3048 struct stats_admin_rule *rule;
3049
3050 if (curproxy == &defproxy) {
3051 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055
3056 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3057 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3058 err_code |= ERR_ALERT | ERR_ABORT;
3059 goto out;
3060 }
3061
3062 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3063 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3064 file, linenum, args[0], args[1]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003068 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3069 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3070 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003071 err_code |= ERR_ALERT | ERR_FATAL;
3072 goto out;
3073 }
3074
3075 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3076
3077 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3078 rule->cond = cond;
3079 LIST_INIT(&rule->list);
3080 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 } else if (!strcmp(args[1], "uri")) {
3082 if (*(args[2]) == 0) {
3083 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3087 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_ABORT;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 }
3091 } else if (!strcmp(args[1], "realm")) {
3092 if (*(args[2]) == 0) {
3093 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3097 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_ABORT;
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003101 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003102 unsigned interval;
3103
3104 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3105 if (err) {
3106 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3107 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003110 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3111 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_ABORT;
3113 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003114 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003115 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003116 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003117
3118 if (curproxy == &defproxy) {
3119 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
3123
3124 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3125 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3126 err_code |= ERR_ALERT | ERR_ABORT;
3127 goto out;
3128 }
3129
Willy Tarreauff011f22011-01-06 17:51:27 +01003130 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3131 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003132 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3133 file, linenum, args[0]);
3134 err_code |= ERR_WARN;
3135 }
3136
Willy Tarreauff011f22011-01-06 17:51:27 +01003137 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003138
Willy Tarreauff011f22011-01-06 17:51:27 +01003139 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003140 err_code |= ERR_ALERT | ERR_ABORT;
3141 goto out;
3142 }
3143
Willy Tarreauff011f22011-01-06 17:51:27 +01003144 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3145 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 } else if (!strcmp(args[1], "auth")) {
3148 if (*(args[2]) == 0) {
3149 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_ABORT;
3155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
3157 } else if (!strcmp(args[1], "scope")) {
3158 if (*(args[2]) == 0) {
3159 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3163 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167 } else if (!strcmp(args[1], "enable")) {
3168 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3169 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_ABORT;
3171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003173 } else if (!strcmp(args[1], "hide-version")) {
3174 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3175 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_ABORT;
3177 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003178 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003179 } else if (!strcmp(args[1], "show-legends")) {
3180 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3181 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3182 err_code |= ERR_ALERT | ERR_ABORT;
3183 goto out;
3184 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003185 } else if (!strcmp(args[1], "show-node")) {
3186
3187 if (*args[2]) {
3188 int i;
3189 char c;
3190
3191 for (i=0; args[2][i]; i++) {
3192 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003193 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3194 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003195 break;
3196 }
3197
3198 if (!i || args[2][i]) {
3199 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3200 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3201 file, linenum, args[0], args[1]);
3202 err_code |= ERR_ALERT | ERR_FATAL;
3203 goto out;
3204 }
3205 }
3206
3207 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3208 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
3211 }
3212 } else if (!strcmp(args[1], "show-desc")) {
3213 char *desc = NULL;
3214
3215 if (*args[2]) {
3216 int i, len=0;
3217 char *d;
3218
3219 for(i=2; *args[i]; i++)
3220 len += strlen(args[i])+1;
3221
3222 desc = d = (char *)calloc(1, len);
3223
3224 d += sprintf(d, "%s", args[2]);
3225 for(i=3; *args[i]; i++)
3226 d += sprintf(d, " %s", args[i]);
3227 }
3228
3229 if (!*args[2] && !global.desc)
3230 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3231 file, linenum, args[1]);
3232 else {
3233 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3234 free(desc);
3235 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3236 err_code |= ERR_ALERT | ERR_ABORT;
3237 goto out;
3238 }
3239 free(desc);
3240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003242stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003243 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 +01003244 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 }
3248 }
3249 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003250 int optnum;
3251
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003252 if (*(args[1]) == '\0') {
3253 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3254 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003258
3259 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3260 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003261 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3262 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3263 file, linenum, cfg_opts[optnum].name);
3264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
3266 }
Willy Tarreau93893792009-07-23 13:19:11 +02003267 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3268 err_code |= ERR_WARN;
3269 goto out;
3270 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003271
Willy Tarreau3842f002009-06-14 11:39:52 +02003272 curproxy->no_options &= ~cfg_opts[optnum].val;
3273 curproxy->options &= ~cfg_opts[optnum].val;
3274
3275 switch (kwm) {
3276 case KWM_STD:
3277 curproxy->options |= cfg_opts[optnum].val;
3278 break;
3279 case KWM_NO:
3280 curproxy->no_options |= cfg_opts[optnum].val;
3281 break;
3282 case KWM_DEF: /* already cleared */
3283 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003284 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003285
Willy Tarreau93893792009-07-23 13:19:11 +02003286 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003287 }
3288 }
3289
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003290 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3291 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003292 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3293 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3294 file, linenum, cfg_opts2[optnum].name);
3295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
3297 }
Willy Tarreau93893792009-07-23 13:19:11 +02003298 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3299 err_code |= ERR_WARN;
3300 goto out;
3301 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003302
Willy Tarreau3842f002009-06-14 11:39:52 +02003303 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3304 curproxy->options2 &= ~cfg_opts2[optnum].val;
3305
3306 switch (kwm) {
3307 case KWM_STD:
3308 curproxy->options2 |= cfg_opts2[optnum].val;
3309 break;
3310 case KWM_NO:
3311 curproxy->no_options2 |= cfg_opts2[optnum].val;
3312 break;
3313 case KWM_DEF: /* already cleared */
3314 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003315 }
Willy Tarreau93893792009-07-23 13:19:11 +02003316 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003317 }
3318 }
3319
Willy Tarreau3842f002009-06-14 11:39:52 +02003320 if (kwm != KWM_STD) {
3321 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003322 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003325 }
3326
Emeric Brun3a058f32009-06-30 18:26:00 +02003327 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003328 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003330 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003331 if (*(args[2]) != '\0') {
3332 if (!strcmp(args[2], "clf")) {
3333 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003334 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003335 } else {
3336 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003339 }
3340 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003341 if (curproxy->logformat_string != default_http_log_format &&
3342 curproxy->logformat_string != default_tcp_log_format &&
3343 curproxy->logformat_string != clf_http_log_format)
3344 free(curproxy->logformat_string);
3345 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003346 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003347 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003349 if (curproxy->logformat_string != default_http_log_format &&
3350 curproxy->logformat_string != default_tcp_log_format &&
3351 curproxy->logformat_string != clf_http_log_format)
3352 free(curproxy->logformat_string);
3353 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 else if (!strcmp(args[1], "tcpka")) {
3356 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003357 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003359
3360 if (curproxy->cap & PR_CAP_FE)
3361 curproxy->options |= PR_O_TCP_CLI_KA;
3362 if (curproxy->cap & PR_CAP_BE)
3363 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 }
3365 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003366 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_WARN;
3368
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003370 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003371 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003372 curproxy->options2 &= ~PR_O2_CHK_ANY;
3373 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 if (!*args[2]) { /* no argument */
3375 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3376 curproxy->check_len = strlen(DEF_CHECK_REQ);
3377 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003378 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 curproxy->check_req = (char *)malloc(reqlen);
3380 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003381 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003383 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 if (*args[4])
3385 reqlen += strlen(args[4]);
3386 else
3387 reqlen += strlen("HTTP/1.0");
3388
3389 curproxy->check_req = (char *)malloc(reqlen);
3390 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003391 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003393 }
3394 else if (!strcmp(args[1], "ssl-hello-chk")) {
3395 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003398
Willy Tarreaua534fea2008-08-03 12:19:50 +02003399 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003400 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003401 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003402 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
Willy Tarreau23677902007-05-08 23:50:35 +02003404 else if (!strcmp(args[1], "smtpchk")) {
3405 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003406 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003407 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003408 curproxy->options2 &= ~PR_O2_CHK_ANY;
3409 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003410
3411 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3412 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3413 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3414 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3415 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3416 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3417 curproxy->check_req = (char *)malloc(reqlen);
3418 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3419 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3420 } else {
3421 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3422 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3423 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3424 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3425 }
3426 }
3427 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003428 else if (!strcmp(args[1], "pgsql-check")) {
3429 /* use PostgreSQL request to check servers' health */
3430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3431 err_code |= ERR_WARN;
3432
3433 free(curproxy->check_req);
3434 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003435 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003436 curproxy->options2 |= PR_O2_PGSQL_CHK;
3437
3438 if (*(args[2])) {
3439 int cur_arg = 2;
3440
3441 while (*(args[cur_arg])) {
3442 if (strcmp(args[cur_arg], "user") == 0) {
3443 char * packet;
3444 uint32_t packet_len;
3445 uint32_t pv;
3446
3447 /* suboption header - needs additional argument for it */
3448 if (*(args[cur_arg+1]) == 0) {
3449 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3450 file, linenum, args[0], args[1], args[cur_arg]);
3451 err_code |= ERR_ALERT | ERR_FATAL;
3452 goto out;
3453 }
3454
3455 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3456 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3457 pv = htonl(0x30000); /* protocol version 3.0 */
3458
3459 packet = (char*) calloc(1, packet_len);
3460
3461 memcpy(packet + 4, &pv, 4);
3462
3463 /* copy "user" */
3464 memcpy(packet + 8, "user", 4);
3465
3466 /* copy username */
3467 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3468
3469 free(curproxy->check_req);
3470 curproxy->check_req = packet;
3471 curproxy->check_len = packet_len;
3472
3473 packet_len = htonl(packet_len);
3474 memcpy(packet, &packet_len, 4);
3475 cur_arg += 2;
3476 } else {
3477 /* unknown suboption - catchall */
3478 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3479 file, linenum, args[0], args[1]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
3483 } /* end while loop */
3484 }
3485 }
3486
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003487 else if (!strcmp(args[1], "redis-check")) {
3488 /* use REDIS PING request to check servers' health */
3489 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3490 err_code |= ERR_WARN;
3491
3492 free(curproxy->check_req);
3493 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003494 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003495 curproxy->options2 |= PR_O2_REDIS_CHK;
3496
3497 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3498 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3499 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3500 }
3501
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003502 else if (!strcmp(args[1], "mysql-check")) {
3503 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003504 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3505 err_code |= ERR_WARN;
3506
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003507 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003508 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003509 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003510 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003511
3512 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3513 * const char mysql40_client_auth_pkt[] = {
3514 * "\x0e\x00\x00" // packet length
3515 * "\x01" // packet number
3516 * "\x00\x00" // client capabilities
3517 * "\x00\x00\x01" // max packet
3518 * "haproxy\x00" // username (null terminated string)
3519 * "\x00" // filler (always 0x00)
3520 * "\x01\x00\x00" // packet length
3521 * "\x00" // packet number
3522 * "\x01" // COM_QUIT command
3523 * };
3524 */
3525
3526 if (*(args[2])) {
3527 int cur_arg = 2;
3528
3529 while (*(args[cur_arg])) {
3530 if (strcmp(args[cur_arg], "user") == 0) {
3531 char *mysqluser;
3532 int packetlen, reqlen, userlen;
3533
3534 /* suboption header - needs additional argument for it */
3535 if (*(args[cur_arg+1]) == 0) {
3536 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3537 file, linenum, args[0], args[1], args[cur_arg]);
3538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
3540 }
3541 mysqluser = args[cur_arg + 1];
3542 userlen = strlen(mysqluser);
3543 packetlen = userlen + 7;
3544 reqlen = packetlen + 9;
3545
3546 free(curproxy->check_req);
3547 curproxy->check_req = (char *)calloc(1, reqlen);
3548 curproxy->check_len = reqlen;
3549
3550 snprintf(curproxy->check_req, 4, "%c%c%c",
3551 ((unsigned char) packetlen & 0xff),
3552 ((unsigned char) (packetlen >> 8) & 0xff),
3553 ((unsigned char) (packetlen >> 16) & 0xff));
3554
3555 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003556 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003557 curproxy->check_req[8] = 1;
3558 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3559 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3560 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3561 cur_arg += 2;
3562 } else {
3563 /* unknown suboption - catchall */
3564 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3565 file, linenum, args[0], args[1]);
3566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
3568 }
3569 } /* end while loop */
3570 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003571 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003572 else if (!strcmp(args[1], "ldap-check")) {
3573 /* use LDAP request to check servers' health */
3574 free(curproxy->check_req);
3575 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003576 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003577 curproxy->options2 |= PR_O2_LDAP_CHK;
3578
3579 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3580 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3581 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3582 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003583 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003584 int cur_arg;
3585
3586 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3587 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003588 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003589
Willy Tarreau87cf5142011-08-19 22:57:24 +02003590 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003591
3592 free(curproxy->fwdfor_hdr_name);
3593 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3594 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3595
3596 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3597 cur_arg = 2;
3598 while (*(args[cur_arg])) {
3599 if (!strcmp(args[cur_arg], "except")) {
3600 /* suboption except - needs additional argument for it */
3601 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3602 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3603 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003606 }
3607 /* flush useless bits */
3608 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003609 cur_arg += 2;
3610 } else if (!strcmp(args[cur_arg], "header")) {
3611 /* suboption header - needs additional argument for it */
3612 if (*(args[cur_arg+1]) == 0) {
3613 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3614 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003617 }
3618 free(curproxy->fwdfor_hdr_name);
3619 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3620 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3621 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003622 } else if (!strcmp(args[cur_arg], "if-none")) {
3623 curproxy->options &= ~PR_O_FF_ALWAYS;
3624 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003625 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003626 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003627 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003628 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003631 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003632 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003633 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003634 else if (!strcmp(args[1], "originalto")) {
3635 int cur_arg;
3636
3637 /* insert x-original-to field, but not for the IP address listed as an except.
3638 * set default options (ie: bitfield, header name, etc)
3639 */
3640
3641 curproxy->options |= PR_O_ORGTO;
3642
3643 free(curproxy->orgto_hdr_name);
3644 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3645 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3646
Willy Tarreau87cf5142011-08-19 22:57:24 +02003647 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003648 cur_arg = 2;
3649 while (*(args[cur_arg])) {
3650 if (!strcmp(args[cur_arg], "except")) {
3651 /* suboption except - needs additional argument for it */
3652 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3653 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3654 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003657 }
3658 /* flush useless bits */
3659 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3660 cur_arg += 2;
3661 } else if (!strcmp(args[cur_arg], "header")) {
3662 /* suboption header - needs additional argument for it */
3663 if (*(args[cur_arg+1]) == 0) {
3664 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3665 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003668 }
3669 free(curproxy->orgto_hdr_name);
3670 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3671 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3672 cur_arg += 2;
3673 } else {
3674 /* unknown suboption - catchall */
3675 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3676 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003679 }
3680 } /* end while loop */
3681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 else {
3683 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 }
Willy Tarreau93893792009-07-23 13:19:11 +02003687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003689 else if (!strcmp(args[0], "default_backend")) {
3690 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003691 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003692
3693 if (*(args[1]) == 0) {
3694 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003697 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003698 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003699 curproxy->defbe.name = strdup(args[1]);
3700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003701 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003702 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003704
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003705 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3706 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 /* enable reconnections to dispatch */
3709 curproxy->options |= PR_O_REDISP;
3710 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003711 else if (!strcmp(args[0], "http-check")) {
3712 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003714
3715 if (strcmp(args[1], "disable-on-404") == 0) {
3716 /* enable a graceful server shutdown on an HTTP 404 response */
3717 curproxy->options |= PR_O_DISABLE404;
3718 }
Willy Tarreauef781042010-01-27 11:53:01 +01003719 else if (strcmp(args[1], "send-state") == 0) {
3720 /* enable emission of the apparent state of a server in HTTP checks */
3721 curproxy->options2 |= PR_O2_CHK_SNDST;
3722 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003723 else if (strcmp(args[1], "expect") == 0) {
3724 const char *ptr_arg;
3725 int cur_arg;
3726
3727 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3728 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732
3733 cur_arg = 2;
3734 /* consider exclamation marks, sole or at the beginning of a word */
3735 while (*(ptr_arg = args[cur_arg])) {
3736 while (*ptr_arg == '!') {
3737 curproxy->options2 ^= PR_O2_EXP_INV;
3738 ptr_arg++;
3739 }
3740 if (*ptr_arg)
3741 break;
3742 cur_arg++;
3743 }
3744 /* now ptr_arg points to the beginning of a word past any possible
3745 * exclamation mark, and cur_arg is the argument which holds this word.
3746 */
3747 if (strcmp(ptr_arg, "status") == 0) {
3748 if (!*(args[cur_arg + 1])) {
3749 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3750 file, linenum, args[0], args[1], ptr_arg);
3751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
3753 }
3754 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003755 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003756 curproxy->expect_str = strdup(args[cur_arg + 1]);
3757 }
3758 else if (strcmp(ptr_arg, "string") == 0) {
3759 if (!*(args[cur_arg + 1])) {
3760 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3761 file, linenum, args[0], args[1], ptr_arg);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003766 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003767 curproxy->expect_str = strdup(args[cur_arg + 1]);
3768 }
3769 else if (strcmp(ptr_arg, "rstatus") == 0) {
3770 if (!*(args[cur_arg + 1])) {
3771 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3772 file, linenum, args[0], args[1], ptr_arg);
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
3776 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003777 free(curproxy->expect_str);
3778 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3779 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003780 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3781 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3782 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3783 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
3787 }
3788 else if (strcmp(ptr_arg, "rstring") == 0) {
3789 if (!*(args[cur_arg + 1])) {
3790 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3791 file, linenum, args[0], args[1], ptr_arg);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
3794 }
3795 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003796 free(curproxy->expect_str);
3797 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3798 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003799 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3800 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3801 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3802 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806 }
3807 else {
3808 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3809 file, linenum, args[0], args[1], ptr_arg);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003814 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003815 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 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003818 }
3819 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003820 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003821 if (curproxy == &defproxy) {
3822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003825 }
3826
Willy Tarreaub80c2302007-11-30 20:51:32 +01003827 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003829
3830 if (strcmp(args[1], "fail") == 0) {
3831 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003832 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003833 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3834 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003837 }
3838
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003839 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3840 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3841 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003844 }
3845 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3846 }
3847 else {
3848 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003851 }
3852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853#ifdef TPROXY
3854 else if (!strcmp(args[0], "transparent")) {
3855 /* enable transparent proxy connections */
3856 curproxy->options |= PR_O_TRANSP;
3857 }
3858#endif
3859 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003862
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 if (*(args[1]) == 0) {
3864 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868 curproxy->maxconn = atol(args[1]);
3869 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003870 else if (!strcmp(args[0], "backlog")) { /* backlog */
3871 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003873
3874 if (*(args[1]) == 0) {
3875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003878 }
3879 curproxy->backlog = atol(args[1]);
3880 }
Willy Tarreau86034312006-12-29 00:10:33 +01003881 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003882 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003884
Willy Tarreau86034312006-12-29 00:10:33 +01003885 if (*(args[1]) == 0) {
3886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003889 }
3890 curproxy->fullconn = atol(args[1]);
3891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3893 if (*(args[1]) == 0) {
3894 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003898 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3899 if (err) {
3900 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3901 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003904 }
3905 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
3907 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003908 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 if (curproxy == &defproxy) {
3910 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003913 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003914 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003916
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 if (strchr(args[1], ':') == NULL) {
3918 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003922 sk = str2sa(args[1]);
3923 if (!sk) {
3924 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
3927 }
3928 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003929 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 }
3931 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003932 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003934
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003935 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3936 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003941 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3942 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3943 err_code |= ERR_WARN;
3944
3945 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3946 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3947 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3948 }
3949 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3950 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3951 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3952 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003953 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3954 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3955 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3956 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003957 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003958 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
3962 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003963 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 char *rport, *raddr;
3966 short realport = 0;
3967 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003969 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003974 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976
3977 if (!*args[2]) {
3978 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3979 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003983
3984 err = invalid_char(args[1]);
3985 if (err) {
3986 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3987 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003990 }
3991
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003993 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003994
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003995 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3996 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3997 err_code |= ERR_ALERT | ERR_ABORT;
3998 goto out;
3999 }
4000
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004001 /* the servers are linked backwards first */
4002 newsrv->next = curproxy->srv;
4003 curproxy->srv = newsrv;
4004 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004005 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004006 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007
Simon Hormanaf514952011-06-21 14:34:57 +09004008 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004009 LIST_INIT(&newsrv->pendconns);
4010 do_check = 0;
4011 newsrv->state = SRV_RUNNING; /* early server setup */
4012 newsrv->last_change = now.tv_sec;
4013 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004014
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004015 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004016 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 * - IP: => port=+0, relative
4018 * - IP:N => port=N, absolute
4019 * - IP:+N => port=+N, relative
4020 * - IP:-N => port=-N, relative
4021 */
4022 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004023 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 if (rport) {
4025 *rport++ = 0;
4026 realport = atol(rport);
4027 if (!isdigit((unsigned char)*rport))
4028 newsrv->state |= SRV_MAPPORTS;
4029 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031
Willy Tarreaufab5a432011-03-04 15:31:53 +01004032 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004033 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004034 if (!sk) {
4035 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004040 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4041 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004042
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004043 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004044 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4045 file, linenum, newsrv->addr.ss_family, args[2]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004049 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004051 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004052 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 newsrv->inter = curproxy->defsrv.inter;
4054 newsrv->fastinter = curproxy->defsrv.fastinter;
4055 newsrv->downinter = curproxy->defsrv.downinter;
4056 newsrv->rise = curproxy->defsrv.rise;
4057 newsrv->fall = curproxy->defsrv.fall;
4058 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4059 newsrv->minconn = curproxy->defsrv.minconn;
4060 newsrv->maxconn = curproxy->defsrv.maxconn;
4061 newsrv->slowstart = curproxy->defsrv.slowstart;
4062 newsrv->onerror = curproxy->defsrv.onerror;
4063 newsrv->consecutive_errors_limit
4064 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004065#ifdef OPENSSL
4066 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4067#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 newsrv->uweight = newsrv->iweight
4069 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004072
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004073 cur_arg = 3;
4074 } else {
4075 newsrv = &curproxy->defsrv;
4076 cur_arg = 1;
4077 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004078
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004080 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 newsrv->cookie = strdup(args[cur_arg + 1]);
4082 newsrv->cklen = strlen(args[cur_arg + 1]);
4083 cur_arg += 2;
4084 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004085 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004086 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4087 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4088 cur_arg += 2;
4089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004091 if (!*args[cur_arg + 1]) {
4092 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4093 file, linenum, args[cur_arg]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004099 if (newsrv->rise <= 0) {
4100 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4101 file, linenum, args[cur_arg]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
4105
Willy Tarreau96839092010-03-29 10:02:24 +02004106 if (newsrv->health)
4107 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 cur_arg += 2;
4109 }
4110 else if (!strcmp(args[cur_arg], "fall")) {
4111 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004112
4113 if (!*args[cur_arg + 1]) {
4114 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4115 file, linenum, args[cur_arg]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119
4120 if (newsrv->fall <= 0) {
4121 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4122 file, linenum, args[cur_arg]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 cur_arg += 2;
4128 }
4129 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004130 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4131 if (err) {
4132 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4133 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004136 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004137 if (val <= 0) {
4138 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4139 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004142 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004143 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 cur_arg += 2;
4145 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004146 else if (!strcmp(args[cur_arg], "fastinter")) {
4147 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4148 if (err) {
4149 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4150 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004153 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004154 if (val <= 0) {
4155 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4156 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004159 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004160 newsrv->fastinter = val;
4161 cur_arg += 2;
4162 }
4163 else if (!strcmp(args[cur_arg], "downinter")) {
4164 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4165 if (err) {
4166 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4167 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004170 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004171 if (val <= 0) {
4172 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4173 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004176 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004177 newsrv->downinter = val;
4178 cur_arg += 2;
4179 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004180 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004181 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004182 if (!sk) {
4183 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004187 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004188 cur_arg += 2;
4189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004190 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004191 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 cur_arg += 2;
4193 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004194 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 newsrv->state |= SRV_BACKUP;
4196 cur_arg ++;
4197 }
Simon Hormanfa461682011-06-25 09:39:49 +09004198 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4199 newsrv->state |= SRV_NON_STICK;
4200 cur_arg ++;
4201 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004202 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4203 newsrv->state |= SRV_SEND_PROXY;
4204 cur_arg ++;
4205 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004206 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4207 newsrv->check.send_proxy = 1;
4208 cur_arg ++;
4209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 else if (!strcmp(args[cur_arg], "weight")) {
4211 int w;
4212 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004213 if (w < 0 || w > 256) {
4214 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004219 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 cur_arg += 2;
4221 }
4222 else if (!strcmp(args[cur_arg], "minconn")) {
4223 newsrv->minconn = atol(args[cur_arg + 1]);
4224 cur_arg += 2;
4225 }
4226 else if (!strcmp(args[cur_arg], "maxconn")) {
4227 newsrv->maxconn = atol(args[cur_arg + 1]);
4228 cur_arg += 2;
4229 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004230 else if (!strcmp(args[cur_arg], "maxqueue")) {
4231 newsrv->maxqueue = atol(args[cur_arg + 1]);
4232 cur_arg += 2;
4233 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004234 else if (!strcmp(args[cur_arg], "slowstart")) {
4235 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004236 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004237 if (err) {
4238 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4239 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004242 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004243 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004244 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4245 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004248 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004249 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004250 cur_arg += 2;
4251 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004252 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004253
4254 if (!*args[cur_arg + 1]) {
4255 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4256 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004259 }
4260
4261 newsrv->trackit = strdup(args[cur_arg + 1]);
4262
4263 cur_arg += 2;
4264 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004265 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004266 global.maxsock++;
4267 do_check = 1;
4268 cur_arg += 1;
4269 }
Willy Tarreau96839092010-03-29 10:02:24 +02004270 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4271 newsrv->state |= SRV_MAINTAIN;
4272 newsrv->state &= ~SRV_RUNNING;
4273 newsrv->health = 0;
4274 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004275 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004276 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004277 if (!strcmp(args[cur_arg + 1], "none"))
4278 newsrv->observe = HANA_OBS_NONE;
4279 else if (!strcmp(args[cur_arg + 1], "layer4"))
4280 newsrv->observe = HANA_OBS_LAYER4;
4281 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4282 if (curproxy->mode != PR_MODE_HTTP) {
4283 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4284 file, linenum, args[cur_arg + 1]);
4285 err_code |= ERR_ALERT;
4286 }
4287 newsrv->observe = HANA_OBS_LAYER7;
4288 }
4289 else {
4290 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004291 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004292 file, linenum, args[cur_arg], args[cur_arg + 1]);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296
4297 cur_arg += 2;
4298 }
4299 else if (!strcmp(args[cur_arg], "on-error")) {
4300 if (!strcmp(args[cur_arg + 1], "fastinter"))
4301 newsrv->onerror = HANA_ONERR_FASTINTER;
4302 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4303 newsrv->onerror = HANA_ONERR_FAILCHK;
4304 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4305 newsrv->onerror = HANA_ONERR_SUDDTH;
4306 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4307 newsrv->onerror = HANA_ONERR_MARKDWN;
4308 else {
4309 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004310 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004311 file, linenum, args[cur_arg], args[cur_arg + 1]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315
4316 cur_arg += 2;
4317 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004318 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4319 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4320 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4321 else {
4322 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4323 file, linenum, args[cur_arg], args[cur_arg + 1]);
4324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
4326 }
4327
4328 cur_arg += 2;
4329 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004330 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4331 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4332 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4333 else {
4334 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4335 file, linenum, args[cur_arg], args[cur_arg + 1]);
4336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339
4340 cur_arg += 2;
4341 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004342 else if (!strcmp(args[cur_arg], "error-limit")) {
4343 if (!*args[cur_arg + 1]) {
4344 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4345 file, linenum, args[cur_arg]);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349
4350 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4351
4352 if (newsrv->consecutive_errors_limit <= 0) {
4353 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4354 file, linenum, args[cur_arg]);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004358 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004359 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004360 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004361 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004362 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004363
Willy Tarreaubaaee002006-06-26 02:48:02 +02004364 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004365#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004366 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004367 file, linenum, "source", "usesrc");
4368#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004369 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004370 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004371#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 }
4375 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4377 if (!sk) {
4378 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
4381 }
4382 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004383
4384 if (port_low != port_high) {
4385 int i;
4386 if (port_low <= 0 || port_low > 65535 ||
4387 port_high <= 0 || port_high > 65535 ||
4388 port_low > port_high) {
4389 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4390 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004393 }
4394 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4395 for (i = 0; i < newsrv->sport_range->size; i++)
4396 newsrv->sport_range->ports[i] = port_low + i;
4397 }
4398
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 while (*(args[cur_arg])) {
4401 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004402#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4403#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4405 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4406 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004409 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004410#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004411 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004412 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416 }
4417 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004418 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004419 newsrv->state |= SRV_TPROXY_CLI;
4420 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004421 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004423 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4424 char *name, *end;
4425
4426 name = args[cur_arg+1] + 7;
4427 while (isspace(*name))
4428 name++;
4429
4430 end = name;
4431 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4432 end++;
4433
4434 newsrv->state &= ~SRV_TPROXY_MASK;
4435 newsrv->state |= SRV_TPROXY_DYN;
4436 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4437 newsrv->bind_hdr_len = end - name;
4438 memcpy(newsrv->bind_hdr_name, name, end - name);
4439 newsrv->bind_hdr_name[end-name] = '\0';
4440 newsrv->bind_hdr_occ = -1;
4441
4442 /* now look for an occurrence number */
4443 while (isspace(*end))
4444 end++;
4445 if (*end == ',') {
4446 end++;
4447 name = end;
4448 if (*end == '-')
4449 end++;
4450 while (isdigit(*end))
4451 end++;
4452 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4453 }
4454
4455 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4456 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4457 " occurrences values smaller than %d.\n",
4458 file, linenum, MAX_HDR_HISTORY);
4459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
4461 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004462 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004463 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004464 if (!sk) {
4465 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
4468 }
4469 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004470 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004471 }
4472 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004473#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004474 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004475#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004476 cur_arg += 2;
4477 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004478#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004479 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004480 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4484 } /* "usesrc" */
4485
4486 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4487#ifdef SO_BINDTODEVICE
4488 if (!*args[cur_arg + 1]) {
4489 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4490 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004493 }
4494 if (newsrv->iface_name)
4495 free(newsrv->iface_name);
4496
4497 newsrv->iface_name = strdup(args[cur_arg + 1]);
4498 newsrv->iface_len = strlen(newsrv->iface_name);
4499 global.last_checks |= LSTCHK_NETADM;
4500#else
4501 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4502 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004505#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004506 cur_arg += 2;
4507 continue;
4508 }
4509 /* this keyword in not an option of "source" */
4510 break;
4511 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004513 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004514 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4515 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004520 static int srv_dumped;
4521 struct srv_kw *kw;
4522 char *err;
4523
4524 kw = srv_find_kw(args[cur_arg]);
4525 if (kw) {
4526 char *err = NULL;
4527 int code;
4528
4529 if (!kw->parse) {
4530 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4531 file, linenum, args[0], args[1], args[cur_arg]);
4532 cur_arg += 1 + kw->skip ;
4533 err_code |= ERR_ALERT | ERR_FATAL;
4534 goto out;
4535 }
4536
4537 if (defsrv && !kw->default_ok) {
4538 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4539 file, linenum, args[0], args[1], args[cur_arg]);
4540 cur_arg += 1 + kw->skip ;
4541 err_code |= ERR_ALERT;
4542 continue;
4543 }
4544
4545 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4546 err_code |= code;
4547
4548 if (code) {
4549 if (err && *err) {
4550 indent_msg(&err, 2);
4551 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4552 }
4553 else
4554 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4555 file, linenum, args[0], args[1], args[cur_arg]);
4556 if (code & ERR_FATAL) {
4557 free(err);
4558 cur_arg += 1 + kw->skip;
4559 goto out;
4560 }
4561 }
4562 free(err);
4563 cur_arg += 1 + kw->skip;
4564 continue;
4565 }
4566
4567 err = NULL;
4568 if (!srv_dumped) {
4569 srv_dump_kws(&err);
4570 indent_msg(&err, 4);
4571 srv_dumped = 1;
4572 }
4573
4574 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4575 file, linenum, args[0], args[1], args[cur_arg],
4576 err ? " Registered keywords :" : "", err ? err : "");
4577 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004578
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 }
4582 }
4583
4584 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004585 if (newsrv->trackit) {
4586 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4587 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004590 }
4591
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004592 /* If neither a port nor an addr was specified and no check transport
4593 * layer is forced, then the transport layer used by the checks is the
4594 * same as for the production traffic. Otherwise we use raw_sock by
4595 * default, unless one is specified.
4596 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004597 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004598#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004599 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004600#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004601 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4602 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004603 /* try to get the port from check.addr if check.port not set */
4604 if (!newsrv->check.port)
4605 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004606
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004607 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4608 newsrv->check.port = realport; /* by default */
4609 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004610 /* not yet valid, because no port was set on
4611 * the server either. We'll check if we have
4612 * a known port on the first listener.
4613 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004614 struct listener *l;
4615
4616 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004617 newsrv->check.port = get_host_port(&l->addr);
4618 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004619 break;
4620 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004621 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004622 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4624 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004628
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004629 /* Allocate buffer for check requests... */
4630 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004631 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4632 err_code |= ERR_ALERT | ERR_ABORT;
4633 goto out;
4634 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004635 newsrv->check.bi->size = global.tune.chksize;
4636
4637 /* Allocate buffer for check responses... */
4638 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4639 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4640 err_code |= ERR_ALERT | ERR_ABORT;
4641 goto out;
4642 }
4643 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004644
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004645 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004646 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004647 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4648 err_code |= ERR_ALERT | ERR_ABORT;
4649 goto out;
4650 }
4651
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004652 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4653 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654 newsrv->state |= SRV_CHECKED;
4655 }
4656
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004657 if (!defsrv) {
4658 if (newsrv->state & SRV_BACKUP)
4659 curproxy->srv_bck++;
4660 else
4661 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004662
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004663 newsrv->prev_state = newsrv->state;
4664 }
William Lallemanda73203e2012-03-12 12:48:57 +01004665 }
4666
4667 else if (strcmp(args[0], "unique-id-format") == 0) {
4668 if (!*(args[1])) {
4669 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
4672 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004673 free(curproxy->uniqueid_format_string);
4674 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004675 }
William Lallemanda73203e2012-03-12 12:48:57 +01004676
4677 else if (strcmp(args[0], "unique-id-header") == 0) {
4678 if (!*(args[1])) {
4679 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683 free(curproxy->header_unique_id);
4684 curproxy->header_unique_id = strdup(args[1]);
4685 }
4686
William Lallemand723b73a2012-02-08 16:37:49 +01004687 else if (strcmp(args[0], "log-format") == 0) {
4688 if (!*(args[1])) {
4689 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004693
4694 if (curproxy->logformat_string != default_http_log_format &&
4695 curproxy->logformat_string != default_tcp_log_format &&
4696 curproxy->logformat_string != clf_http_log_format)
4697 free(curproxy->logformat_string);
4698 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
William Lallemand723b73a2012-02-08 16:37:49 +01004700
William Lallemand0f99e342011-10-12 17:50:54 +02004701 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4702 /* delete previous herited or defined syslog servers */
4703 struct logsrv *back;
4704
4705 if (*(args[1]) != 0) {
4706 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
4710
William Lallemand723b73a2012-02-08 16:37:49 +01004711 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4712 LIST_DEL(&tmplogsrv->list);
4713 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004714 }
4715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004717 struct logsrv *logsrv;
4718
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004720 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004721 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004722 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004723 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004724 LIST_INIT(&node->list);
4725 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 }
4728 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004729
4730 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731
William Lallemand0f99e342011-10-12 17:50:54 +02004732 logsrv->facility = get_log_facility(args[2]);
4733 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
4739
William Lallemand0f99e342011-10-12 17:50:54 +02004740 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004742 logsrv->level = get_log_level(args[3]);
4743 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
4749 }
4750
William Lallemand0f99e342011-10-12 17:50:54 +02004751 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004752 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004753 logsrv->minlvl = get_log_level(args[4]);
4754 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004755 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
4758
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004759 }
4760 }
4761
Robert Tsai81ae1952007-12-05 10:47:29 +01004762 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004763 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004764 if (!sk) {
4765 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004766 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
4769 }
William Lallemand0f99e342011-10-12 17:50:54 +02004770 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004771 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004772 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004773 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004774 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
William Lallemand0f99e342011-10-12 17:50:54 +02004778 logsrv->addr = *sk;
4779 if (!get_host_port(&logsrv->addr))
4780 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
William Lallemand0f99e342011-10-12 17:50:54 +02004782
4783 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
4785 else {
4786 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4787 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
4791 }
4792 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004793 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004794 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004795
Willy Tarreau977b8e42006-12-29 14:19:17 +01004796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004798
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004800 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4801 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004805
4806 /* we must first clear any optional default setting */
4807 curproxy->options &= ~PR_O_TPXY_MASK;
4808 free(curproxy->iface_name);
4809 curproxy->iface_name = NULL;
4810 curproxy->iface_len = 0;
4811
Willy Tarreaud5191e72010-02-09 20:50:45 +01004812 sk = str2sa(args[1]);
4813 if (!sk) {
4814 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4815 err_code |= ERR_ALERT | ERR_FATAL;
4816 goto out;
4817 }
4818 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004820
4821 cur_arg = 2;
4822 while (*(args[cur_arg])) {
4823 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004824#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4825#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004826 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4827 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4828 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004831 }
4832#endif
4833 if (!*args[cur_arg + 1]) {
4834 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4835 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004838 }
4839
4840 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004841 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004842 curproxy->options |= PR_O_TPXY_CLI;
4843 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004844 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004845 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004846 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4847 char *name, *end;
4848
4849 name = args[cur_arg+1] + 7;
4850 while (isspace(*name))
4851 name++;
4852
4853 end = name;
4854 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4855 end++;
4856
4857 curproxy->options &= ~PR_O_TPXY_MASK;
4858 curproxy->options |= PR_O_TPXY_DYN;
4859 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4860 curproxy->bind_hdr_len = end - name;
4861 memcpy(curproxy->bind_hdr_name, name, end - name);
4862 curproxy->bind_hdr_name[end-name] = '\0';
4863 curproxy->bind_hdr_occ = -1;
4864
4865 /* now look for an occurrence number */
4866 while (isspace(*end))
4867 end++;
4868 if (*end == ',') {
4869 end++;
4870 name = end;
4871 if (*end == '-')
4872 end++;
4873 while (isdigit(*end))
4874 end++;
4875 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4876 }
4877
4878 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4879 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4880 " occurrences values smaller than %d.\n",
4881 file, linenum, MAX_HDR_HISTORY);
4882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004885 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004886 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004887 if (!sk) {
4888 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
4891 }
4892 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004894 }
4895 global.last_checks |= LSTCHK_NETADM;
4896#if !defined(CONFIG_HAP_LINUX_TPROXY)
4897 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004898#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004899#else /* no TPROXY support */
4900 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004901 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004904#endif
4905 cur_arg += 2;
4906 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004907 }
4908
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004909 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4910#ifdef SO_BINDTODEVICE
4911 if (!*args[cur_arg + 1]) {
4912 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4913 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004916 }
4917 if (curproxy->iface_name)
4918 free(curproxy->iface_name);
4919
4920 curproxy->iface_name = strdup(args[cur_arg + 1]);
4921 curproxy->iface_len = strlen(curproxy->iface_name);
4922 global.last_checks |= LSTCHK_NETADM;
4923#else
4924 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4925 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004928#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004929 cur_arg += 2;
4930 continue;
4931 }
4932 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004933 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004938 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4939 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4940 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951
4952 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004953 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004954 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004960 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004961 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
4965 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004967 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004968 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 }
4972 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004974 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004975 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
4979 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004980 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004981 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004982 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004986 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004987 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004988 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004989 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004991 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004992 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004993 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004994 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004995 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004996 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004998 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004999 }
5000 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005002 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005003 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005005 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005014
5015 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005016 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005017 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005018 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
5021 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005023 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005024 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
5028 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005030 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005031 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005034 }
5035 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005037 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005038 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
5042 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005044 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005045 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005049 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005050 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005051 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005052 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005054 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005057 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005058
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 if (curproxy == &defproxy) {
5060 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005064 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 if (*(args[1]) == 0) {
5068 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005072
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005073 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005074 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5075 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5076 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
5079 }
5080 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5081 }
5082 else if (*args[2]) {
5083 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5084 file, linenum, args[0], args[2]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005089 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005090 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005091 wl->s = strdup(args[1]);
5092 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005093 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 }
5095 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005096 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5098 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005102
Willy Tarreauade5ec42010-01-28 19:33:49 +01005103 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005104 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005105 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005108 }
5109 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005110 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005111 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005112 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
5116 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005118 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005119 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
5123 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005124 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5126 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005133 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005139 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005140 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
5144 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005147 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005152 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005153
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 if (curproxy == &defproxy) {
5155 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005159 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 if (*(args[1]) == 0) {
5163 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005168 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005169 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5170 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5171 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175 err_code |= warnif_cond_requires_req(cond, file, linenum);
5176 }
5177 else if (*args[2]) {
5178 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5179 file, linenum, args[0], args[2]);
5180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005184 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005185 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005186 wl->s = strdup(args[1]);
5187 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
5189 else if (!strcmp(args[0], "errorloc") ||
5190 !strcmp(args[0], "errorloc302") ||
5191 !strcmp(args[0], "errorloc303")) { /* error location */
5192 int errnum, errlen;
5193 char *err;
5194
Willy Tarreau977b8e42006-12-29 14:19:17 +01005195 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005197
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005199 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
5203
5204 errnum = atol(args[1]);
5205 if (!strcmp(args[0], "errorloc303")) {
5206 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5207 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5208 } else {
5209 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5210 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5211 }
5212
Willy Tarreau0f772532006-12-23 20:51:41 +01005213 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5214 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005215 chunk_destroy(&curproxy->errmsg[rc]);
5216 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005217 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005220
5221 if (rc >= HTTP_ERR_SIZE) {
5222 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5223 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 free(err);
5225 }
5226 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005227 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5228 int errnum, errlen, fd;
5229 char *err;
5230 struct stat stat;
5231
5232 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005234
5235 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005236 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005239 }
5240
5241 fd = open(args[2], O_RDONLY);
5242 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5243 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5244 file, linenum, args[2], args[1]);
5245 if (fd >= 0)
5246 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005249 }
5250
Willy Tarreau27a674e2009-08-17 07:23:33 +02005251 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252 errlen = stat.st_size;
5253 } else {
5254 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005255 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005256 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005257 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005258 }
5259
5260 err = malloc(errlen); /* malloc() must succeed during parsing */
5261 errnum = read(fd, err, errlen);
5262 if (errnum != errlen) {
5263 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5264 file, linenum, args[2], args[1]);
5265 close(fd);
5266 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005267 err_code |= ERR_ALERT | ERR_FATAL;
5268 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005269 }
5270 close(fd);
5271
5272 errnum = atol(args[1]);
5273 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5274 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005275 chunk_destroy(&curproxy->errmsg[rc]);
5276 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005277 break;
5278 }
5279 }
5280
5281 if (rc >= HTTP_ERR_SIZE) {
5282 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5283 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005284 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005285 free(err);
5286 }
5287 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005288 else if (!strcmp(args[0], "compression")) {
5289 struct comp *comp;
5290 if (curproxy->comp == NULL) {
5291 comp = calloc(1, sizeof(struct comp));
5292 curproxy->comp = comp;
5293 } else {
5294 comp = curproxy->comp;
5295 }
5296
5297 if (!strcmp(args[1], "algo")) {
5298 int cur_arg;
William Lallemand552df672012-11-07 13:21:47 +01005299 struct comp_ctx ctx;
5300
William Lallemand82fe75c2012-10-23 10:25:10 +02005301 cur_arg = 2;
5302 if (!*args[cur_arg]) {
5303 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5304 file, linenum, args[0]);
5305 err_code |= ERR_ALERT | ERR_FATAL;
5306 goto out;
5307 }
5308 while (*(args[cur_arg])) {
5309 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5310 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5311 file, linenum, args[0], args[cur_arg]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
William Lallemand552df672012-11-07 13:21:47 +01005315 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5316 curproxy->comp->algos->end(&ctx);
5317 } else {
5318 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5319 file, linenum, args[0], args[cur_arg]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005323 cur_arg ++;
5324 continue;
5325 }
5326 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005327 else if (!strcmp(args[1], "offload")) {
5328 comp->offload = 1;
5329 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005330 else if (!strcmp(args[1], "type")) {
5331 int cur_arg;
5332 cur_arg = 2;
5333 if (!*args[cur_arg]) {
5334 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5335 file, linenum, args[0]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339 while (*(args[cur_arg])) {
5340 comp_append_type(comp, args[cur_arg]);
5341 cur_arg ++;
5342 continue;
5343 }
5344 }
5345 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005346 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005347 file, linenum, args[0]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005353 struct cfg_kw_list *kwl;
5354 int index;
5355
5356 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5357 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5358 if (kwl->kw[index].section != CFG_LISTEN)
5359 continue;
5360 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5361 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005362 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005363 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005364 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005367 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005368 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005369 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_WARN;
5371 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005372 }
Willy Tarreau93893792009-07-23 13:19:11 +02005373 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005374 }
5375 }
5376 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005377
Willy Tarreau6daf3432008-01-22 16:44:08 +01005378 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
Willy Tarreau93893792009-07-23 13:19:11 +02005382 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005383 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005384 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385}
5386
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005387int
5388cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5389{
5390
5391 int err_code = 0;
5392 const char *err;
5393
5394 if (!strcmp(args[0], "userlist")) { /* new userlist */
5395 struct userlist *newul;
5396
5397 if (!*args[1]) {
5398 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5399 file, linenum, args[0]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403
5404 err = invalid_char(args[1]);
5405 if (err) {
5406 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5407 file, linenum, *err, args[0], args[1]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411
5412 for (newul = userlist; newul; newul = newul->next)
5413 if (!strcmp(newul->name, args[1])) {
5414 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5415 file, linenum, args[1]);
5416 err_code |= ERR_WARN;
5417 goto out;
5418 }
5419
5420 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5421 if (!newul) {
5422 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5423 err_code |= ERR_ALERT | ERR_ABORT;
5424 goto out;
5425 }
5426
5427 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5428 newul->name = strdup(args[1]);
5429
5430 if (!newul->groupusers | !newul->name) {
5431 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5432 err_code |= ERR_ALERT | ERR_ABORT;
5433 goto out;
5434 }
5435
5436 newul->next = userlist;
5437 userlist = newul;
5438
5439 } else if (!strcmp(args[0], "group")) { /* new group */
5440 int cur_arg, i;
5441 const char *err;
5442
5443 if (!*args[1]) {
5444 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5445 file, linenum, args[0]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
5449
5450 err = invalid_char(args[1]);
5451 if (err) {
5452 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5453 file, linenum, *err, args[0], args[1]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457
5458 for(i = 0; i < userlist->grpcnt; i++)
5459 if (!strcmp(userlist->groups[i], args[1])) {
5460 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5461 file, linenum, args[1], userlist->name);
5462 err_code |= ERR_ALERT;
5463 goto out;
5464 }
5465
5466 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5467 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5468 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
5471 }
5472
5473 cur_arg = 2;
5474
5475 while (*args[cur_arg]) {
5476 if (!strcmp(args[cur_arg], "users")) {
5477 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5478 cur_arg += 2;
5479 continue;
5480 } else {
5481 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5482 file, linenum, args[0]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486 }
5487
5488 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5489 } else if (!strcmp(args[0], "user")) { /* new user */
5490 struct auth_users *newuser;
5491 int cur_arg;
5492
5493 if (!*args[1]) {
5494 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5495 file, linenum, args[0]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499
5500 for (newuser = userlist->users; newuser; newuser = newuser->next)
5501 if (!strcmp(newuser->user, args[1])) {
5502 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5503 file, linenum, args[1], userlist->name);
5504 err_code |= ERR_ALERT;
5505 goto out;
5506 }
5507
5508 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5509 if (!newuser) {
5510 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5511 err_code |= ERR_ALERT | ERR_ABORT;
5512 goto out;
5513 }
5514
5515 newuser->user = strdup(args[1]);
5516
5517 newuser->next = userlist->users;
5518 userlist->users = newuser;
5519
5520 cur_arg = 2;
5521
5522 while (*args[cur_arg]) {
5523 if (!strcmp(args[cur_arg], "password")) {
5524#ifndef CONFIG_HAP_CRYPT
5525 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5526 file, linenum);
5527 err_code |= ERR_ALERT;
5528#endif
5529 newuser->pass = strdup(args[cur_arg + 1]);
5530 cur_arg += 2;
5531 continue;
5532 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5533 newuser->pass = strdup(args[cur_arg + 1]);
5534 newuser->flags |= AU_O_INSECURE;
5535 cur_arg += 2;
5536 continue;
5537 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005538 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005539 cur_arg += 2;
5540 continue;
5541 } else {
5542 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5543 file, linenum, args[0]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 }
5547 }
5548 } else {
5549 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5550 err_code |= ERR_ALERT | ERR_FATAL;
5551 }
5552
5553out:
5554 return err_code;
5555}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556
5557/*
5558 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005559 * Returns the error code, 0 if OK, or any combination of :
5560 * - ERR_ABORT: must abort ASAP
5561 * - ERR_FATAL: we can continue parsing but not start the service
5562 * - ERR_WARN: a warning has been emitted
5563 * - ERR_ALERT: an alert has been emitted
5564 * Only the two first ones can stop processing, the two others are just
5565 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005567int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005569 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005570 FILE *f;
5571 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005573 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 if ((f=fopen(file,"r")) == NULL)
5576 return -1;
5577
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005578 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005579 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005580 char *end;
5581 char *args[MAX_LINE_ARGS + 1];
5582 char *line = thisline;
5583
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 linenum++;
5585
5586 end = line + strlen(line);
5587
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005588 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5589 /* Check if we reached the limit and the last char is not \n.
5590 * Watch out for the last line without the terminating '\n'!
5591 */
5592 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005593 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005595 }
5596
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005598 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 line++;
5600
5601 arg = 0;
5602 args[arg] = line;
5603
5604 while (*line && arg < MAX_LINE_ARGS) {
5605 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5606 * C equivalent value. Other combinations left unchanged (eg: \1).
5607 */
5608 if (*line == '\\') {
5609 int skip = 0;
5610 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5611 *line = line[1];
5612 skip = 1;
5613 }
5614 else if (line[1] == 'r') {
5615 *line = '\r';
5616 skip = 1;
5617 }
5618 else if (line[1] == 'n') {
5619 *line = '\n';
5620 skip = 1;
5621 }
5622 else if (line[1] == 't') {
5623 *line = '\t';
5624 skip = 1;
5625 }
5626 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005627 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 unsigned char hex1, hex2;
5629 hex1 = toupper(line[2]) - '0';
5630 hex2 = toupper(line[3]) - '0';
5631 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5632 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5633 *line = (hex1<<4) + hex2;
5634 skip = 3;
5635 }
5636 else {
5637 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 }
5640 }
5641 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005642 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 end -= skip;
5644 }
5645 line++;
5646 }
5647 else if (*line == '#' || *line == '\n' || *line == '\r') {
5648 /* end of string, end of loop */
5649 *line = 0;
5650 break;
5651 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005652 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005654 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005655 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 line++;
5657 args[++arg] = line;
5658 }
5659 else {
5660 line++;
5661 }
5662 }
5663
5664 /* empty line */
5665 if (!**args)
5666 continue;
5667
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005668 if (*line) {
5669 /* we had to stop due to too many args.
5670 * Let's terminate the string, print the offending part then cut the
5671 * last arg.
5672 */
5673 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5674 line++;
5675 *line = '\0';
5676
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005677 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005678 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 args[arg] = line;
5681 }
5682
Willy Tarreau540abe42007-05-02 20:50:16 +02005683 /* zero out remaining args and ensure that at least one entry
5684 * is zeroed out.
5685 */
5686 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 args[arg] = line;
5688 }
5689
Willy Tarreau3842f002009-06-14 11:39:52 +02005690 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005691 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005692 char *tmp;
5693
Willy Tarreau3842f002009-06-14 11:39:52 +02005694 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005695 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005696 for (arg=0; *args[arg+1]; arg++)
5697 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005698 *tmp = '\0'; // fix the next arg to \0
5699 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005700 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005701 else if (!strcmp(args[0], "default")) {
5702 kwm = KWM_DEF;
5703 for (arg=0; *args[arg+1]; arg++)
5704 args[arg] = args[arg+1]; // shift args after inversion
5705 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005706
William Lallemand0f99e342011-10-12 17:50:54 +02005707 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5708 strcmp(args[0], "log") != 0) {
5709 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005711 }
5712
Willy Tarreau977b8e42006-12-29 14:19:17 +01005713 if (!strcmp(args[0], "listen") ||
5714 !strcmp(args[0], "frontend") ||
5715 !strcmp(args[0], "backend") ||
5716 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005717 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005719 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005720 cursection = strdup(args[0]);
5721 }
5722 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005724 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005725 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005726 }
5727 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005728 confsect = CFG_USERLIST;
5729 free(cursection);
5730 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005731 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005732 else if (!strcmp(args[0], "peers")) {
5733 confsect = CFG_PEERS;
5734 free(cursection);
5735 cursection = strdup(args[0]);
5736 }
5737
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 /* else it's a section keyword */
5739
5740 switch (confsect) {
5741 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 break;
5744 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005745 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005747 case CFG_USERLIST:
5748 err_code |= cfg_parse_users(file, linenum, args, kwm);
5749 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005750 case CFG_PEERS:
5751 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5752 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005754 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005757
5758 if (err_code & ERR_ABORT)
5759 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005761 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005762 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005764 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005765}
5766
Willy Tarreaubb925012009-07-23 13:36:36 +02005767/*
5768 * Returns the error code, 0 if OK, or any combination of :
5769 * - ERR_ABORT: must abort ASAP
5770 * - ERR_FATAL: we can continue parsing but not start the service
5771 * - ERR_WARN: a warning has been emitted
5772 * - ERR_ALERT: an alert has been emitted
5773 * Only the two first ones can stop processing, the two others are just
5774 * indicators.
5775 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005776int check_config_validity()
5777{
5778 int cfgerr = 0;
5779 struct proxy *curproxy = NULL;
5780 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005781 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005782 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005783 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005784 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005786 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 /*
5788 * Now, check for the integrity of all that we have collected.
5789 */
5790
5791 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005792 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005794 /* first, we will invert the proxy list order */
5795 curproxy = NULL;
5796 while (proxy) {
5797 struct proxy *next;
5798
5799 next = proxy->next;
5800 proxy->next = curproxy;
5801 curproxy = proxy;
5802 if (!next)
5803 break;
5804 proxy = next;
5805 }
5806
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005808 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005809 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005811 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005812 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005813 unsigned int next_id;
5814
Willy Tarreau050536d2012-10-04 08:47:34 +02005815 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005816 /* proxy ID not set, use automatic numbering with first
5817 * spare entry starting with next_pxid.
5818 */
5819 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5820 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5821 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005822 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005823 next_pxid++;
5824
Willy Tarreau55ea7572007-06-17 19:56:27 +02005825
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005827 /* ensure we don't keep listeners uselessly bound */
5828 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 curproxy = curproxy->next;
5830 continue;
5831 }
5832
Willy Tarreauff01a212009-03-15 13:46:16 +01005833 switch (curproxy->mode) {
5834 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005835 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005836 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005837 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5838 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005839 cfgerr++;
5840 }
5841
5842 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005843 Warning("config : servers will be ignored for %s '%s'.\n",
5844 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005845 break;
5846
5847 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005848 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005849 break;
5850
5851 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005852 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005853 break;
5854 }
5855
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005856 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005857 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005858 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005859 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5860 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005861 cfgerr++;
5862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005864 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005865 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5866 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005867 cfgerr++;
5868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005870 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005871 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5872 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005873 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005874 }
5875 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005876 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005877 /* If no LB algo is set in a backend, and we're not in
5878 * transparent mode, dispatch mode nor proxy mode, we
5879 * want to use balance roundrobin by default.
5880 */
5881 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5882 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 }
5884 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005885
Willy Tarreau1620ec32011-08-06 17:05:02 +02005886 if (curproxy->options & PR_O_DISPATCH)
5887 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5888 else if (curproxy->options & PR_O_HTTP_PROXY)
5889 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5890 else if (curproxy->options & PR_O_TRANSP)
5891 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005892
Willy Tarreau1620ec32011-08-06 17:05:02 +02005893 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5894 if (curproxy->options & PR_O_DISABLE404) {
5895 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5896 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5897 err_code |= ERR_WARN;
5898 curproxy->options &= ~PR_O_DISABLE404;
5899 }
5900 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5901 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5902 "send-state", proxy_type_str(curproxy), curproxy->id);
5903 err_code |= ERR_WARN;
5904 curproxy->options &= ~PR_O2_CHK_SNDST;
5905 }
Willy Tarreauef781042010-01-27 11:53:01 +01005906 }
5907
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005908 /* if a default backend was specified, let's find it */
5909 if (curproxy->defbe.name) {
5910 struct proxy *target;
5911
Alex Williams96532db2009-11-01 21:27:13 -05005912 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005913 if (!target) {
5914 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5915 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005916 cfgerr++;
5917 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005918 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5919 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005920 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005921 } else {
5922 free(curproxy->defbe.name);
5923 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005924 /* we force the backend to be present on at least all of
5925 * the frontend's processes.
5926 */
5927 target->bind_proc = curproxy->bind_proc ?
5928 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005929
5930 /* Emit a warning if this proxy also has some servers */
5931 if (curproxy->srv) {
5932 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5933 curproxy->id);
5934 err_code |= ERR_WARN;
5935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005936 }
5937 }
5938
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005939 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005940 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5941 /* map jump target for ACT_SETBE in req_rep chain */
5942 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005943 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005944 struct proxy *target;
5945
Willy Tarreaua496b602006-12-17 23:15:24 +01005946 if (exp->action != ACT_SETBE)
5947 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005948
Alex Williams96532db2009-11-01 21:27:13 -05005949 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005950 if (!target) {
5951 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5952 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005953 cfgerr++;
5954 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005955 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5956 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005957 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005958 } else {
5959 free((void *)exp->replace);
5960 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005961 /* we force the backend to be present on at least all of
5962 * the frontend's processes.
5963 */
5964 target->bind_proc = curproxy->bind_proc ?
5965 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005966 }
5967 }
5968 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005969
5970 /* find the target proxy for 'use_backend' rules */
5971 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005972 struct proxy *target;
5973
Alex Williams96532db2009-11-01 21:27:13 -05005974 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005975
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005976 if (!target) {
5977 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5978 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005979 cfgerr++;
5980 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005981 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5982 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005983 cfgerr++;
5984 } else {
5985 free((void *)rule->be.name);
5986 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005987 /* we force the backend to be present on at least all of
5988 * the frontend's processes.
5989 */
5990 target->bind_proc = curproxy->bind_proc ?
5991 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005992 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005993 }
5994
5995 /* find the target proxy for 'use_backend' rules */
5996 list_for_each_entry(srule, &curproxy->server_rules, list) {
5997 struct server *target = findserver(curproxy, srule->srv.name);
5998
5999 if (!target) {
6000 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6001 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6002 cfgerr++;
6003 continue;
6004 }
6005 free((void *)srule->srv.name);
6006 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006007 }
6008
Emeric Brunb982a3d2010-01-04 15:45:53 +01006009 /* find the target table for 'stick' rules */
6010 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6011 struct proxy *target;
6012
Emeric Brun1d33b292010-01-04 15:47:17 +01006013 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6014 if (mrule->flags & STK_IS_STORE)
6015 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6016
Emeric Brunb982a3d2010-01-04 15:45:53 +01006017 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006018 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006019 else
6020 target = curproxy;
6021
6022 if (!target) {
6023 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6024 curproxy->id, mrule->table.name);
6025 cfgerr++;
6026 }
6027 else if (target->table.size == 0) {
6028 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6029 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6030 cfgerr++;
6031 }
Willy Tarreau12785782012-04-27 21:37:17 +02006032 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6033 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006034 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6035 cfgerr++;
6036 }
6037 else {
6038 free((void *)mrule->table.name);
6039 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006040 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006041 }
6042 }
6043
6044 /* find the target table for 'store response' rules */
6045 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6046 struct proxy *target;
6047
Emeric Brun1d33b292010-01-04 15:47:17 +01006048 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6049
Emeric Brunb982a3d2010-01-04 15:45:53 +01006050 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006051 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006052 else
6053 target = curproxy;
6054
6055 if (!target) {
6056 Alert("Proxy '%s': unable to find store table '%s'.\n",
6057 curproxy->id, mrule->table.name);
6058 cfgerr++;
6059 }
6060 else if (target->table.size == 0) {
6061 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6062 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6063 cfgerr++;
6064 }
Willy Tarreau12785782012-04-27 21:37:17 +02006065 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6066 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006067 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6068 cfgerr++;
6069 }
6070 else {
6071 free((void *)mrule->table.name);
6072 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006073 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006074 }
6075 }
6076
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006077 /* find the target table for 'tcp-request' layer 4 rules */
6078 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6079 struct proxy *target;
6080
Willy Tarreau56123282010-08-06 19:06:56 +02006081 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006082 continue;
6083
6084 if (trule->act_prm.trk_ctr.table.n)
6085 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6086 else
6087 target = curproxy;
6088
6089 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006090 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6091 curproxy->id, trule->act_prm.trk_ctr.table.n,
6092 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006093 cfgerr++;
6094 }
6095 else if (target->table.size == 0) {
6096 Alert("Proxy '%s': table '%s' used but not configured.\n",
6097 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6098 cfgerr++;
6099 }
6100 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006101 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 +02006102 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6103 cfgerr++;
6104 }
6105 else {
6106 free(trule->act_prm.trk_ctr.table.n);
6107 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006108 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006109 * to pass a list of counters to track and allocate them right here using
6110 * stktable_alloc_data_type().
6111 */
6112 }
6113 }
6114
Willy Tarreaud1f96522010-08-03 19:34:32 +02006115 /* find the target table for 'tcp-request' layer 6 rules */
6116 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6117 struct proxy *target;
6118
Willy Tarreau56123282010-08-06 19:06:56 +02006119 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006120 continue;
6121
6122 if (trule->act_prm.trk_ctr.table.n)
6123 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6124 else
6125 target = curproxy;
6126
6127 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006128 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6129 curproxy->id, trule->act_prm.trk_ctr.table.n,
6130 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006131 cfgerr++;
6132 }
6133 else if (target->table.size == 0) {
6134 Alert("Proxy '%s': table '%s' used but not configured.\n",
6135 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6136 cfgerr++;
6137 }
6138 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006139 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 +02006140 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6141 cfgerr++;
6142 }
6143 else {
6144 free(trule->act_prm.trk_ctr.table.n);
6145 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006146 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006147 * to pass a list of counters to track and allocate them right here using
6148 * stktable_alloc_data_type().
6149 */
6150 }
6151 }
6152
Emeric Brun32da3c42010-09-23 18:39:19 +02006153 if (curproxy->table.peers.name) {
6154 struct peers *curpeers = peers;
6155
6156 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6157 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6158 free((void *)curproxy->table.peers.name);
6159 curproxy->table.peers.p = peers;
6160 break;
6161 }
6162 }
6163
6164 if (!curpeers) {
6165 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6166 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006167 free((void *)curproxy->table.peers.name);
6168 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006169 cfgerr++;
6170 }
6171 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006172 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6173 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006174 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006175 cfgerr++;
6176 }
6177 }
6178
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006179 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006180 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006181 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6182 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6183 "proxy", curproxy->id);
6184 cfgerr++;
6185 goto out_uri_auth_compat;
6186 }
6187
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006188 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006189 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006190 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006191 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006192
Willy Tarreau95fa4692010-02-01 13:05:50 +01006193 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6194 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006195
6196 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006197 uri_auth_compat_req[i++] = "realm";
6198 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6199 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006200
Willy Tarreau95fa4692010-02-01 13:05:50 +01006201 uri_auth_compat_req[i++] = "unless";
6202 uri_auth_compat_req[i++] = "{";
6203 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6204 uri_auth_compat_req[i++] = "}";
6205 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006206
Willy Tarreauff011f22011-01-06 17:51:27 +01006207 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6208 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006209 cfgerr++;
6210 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006211 }
6212
Willy Tarreauff011f22011-01-06 17:51:27 +01006213 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006214
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006215 if (curproxy->uri_auth->auth_realm) {
6216 free(curproxy->uri_auth->auth_realm);
6217 curproxy->uri_auth->auth_realm = NULL;
6218 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006219
6220 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006221 }
6222out_uri_auth_compat:
6223
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006224 cfgerr += acl_find_targets(curproxy);
6225
Willy Tarreau2738a142006-07-08 17:28:09 +02006226 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006227 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006228 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006229 (!curproxy->timeout.connect ||
6230 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006231 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006232 " | While not properly invalid, you will certainly encounter various problems\n"
6233 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006234 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006235 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006236 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006237 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006238
Willy Tarreau1fa31262007-12-03 00:36:16 +01006239 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6240 * We must still support older configurations, so let's find out whether those
6241 * parameters have been set or must be copied from contimeouts.
6242 */
6243 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006244 if (!curproxy->timeout.tarpit ||
6245 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006246 /* tarpit timeout not set. We search in the following order:
6247 * default.tarpit, curr.connect, default.connect.
6248 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006249 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006250 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006251 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006252 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006253 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006254 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006255 }
6256 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006257 (!curproxy->timeout.queue ||
6258 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006259 /* queue timeout not set. We search in the following order:
6260 * default.queue, curr.connect, default.connect.
6261 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006262 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006263 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006264 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006265 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006266 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006267 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006268 }
6269 }
6270
Willy Tarreau1620ec32011-08-06 17:05:02 +02006271 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006272 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6273 curproxy->check_req = (char *)malloc(curproxy->check_len);
6274 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006275 }
6276
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006277 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006278 if (curproxy->nb_req_cap) {
6279 if (curproxy->mode == PR_MODE_HTTP) {
6280 curproxy->req_cap_pool = create_pool("ptrcap",
6281 curproxy->nb_req_cap * sizeof(char *),
6282 MEM_F_SHARED);
6283 } else {
6284 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6285 proxy_type_str(curproxy), curproxy->id);
6286 err_code |= ERR_WARN;
6287 curproxy->to_log &= ~LW_REQHDR;
6288 curproxy->nb_req_cap = 0;
6289 }
6290 }
6291
6292 if (curproxy->nb_rsp_cap) {
6293 if (curproxy->mode == PR_MODE_HTTP) {
6294 curproxy->rsp_cap_pool = create_pool("ptrcap",
6295 curproxy->nb_rsp_cap * sizeof(char *),
6296 MEM_F_SHARED);
6297 } else {
6298 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6299 proxy_type_str(curproxy), curproxy->id);
6300 err_code |= ERR_WARN;
6301 curproxy->to_log &= ~LW_REQHDR;
6302 curproxy->nb_rsp_cap = 0;
6303 }
6304 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006305
Willy Tarreau196729e2012-05-31 19:30:26 +02006306 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006307 if (!(curproxy->cap & PR_CAP_FE)) {
6308 if (curproxy->logformat_string != default_http_log_format &&
6309 curproxy->logformat_string != default_tcp_log_format &&
6310 curproxy->logformat_string != clf_http_log_format)
6311 free(curproxy->logformat_string);
6312 curproxy->logformat_string = NULL;
6313 }
6314
Willy Tarreau196729e2012-05-31 19:30:26 +02006315 if (curproxy->logformat_string)
6316 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6317
6318 if (curproxy->uniqueid_format_string)
6319 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6320
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 /* first, we will invert the servers list order */
6322 newsrv = NULL;
6323 while (curproxy->srv) {
6324 struct server *next;
6325
6326 next = curproxy->srv->next;
6327 curproxy->srv->next = newsrv;
6328 newsrv = curproxy->srv;
6329 if (!next)
6330 break;
6331 curproxy->srv = next;
6332 }
6333
Willy Tarreaudd701652010-05-25 23:03:02 +02006334 /* assign automatic UIDs to servers which don't have one yet */
6335 next_id = 1;
6336 newsrv = curproxy->srv;
6337 while (newsrv != NULL) {
6338 if (!newsrv->puid) {
6339 /* server ID not set, use automatic numbering with first
6340 * spare entry starting with next_svid.
6341 */
6342 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6343 newsrv->conf.id.key = newsrv->puid = next_id;
6344 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6345 }
6346 next_id++;
6347 newsrv = newsrv->next;
6348 }
6349
Willy Tarreau20697042007-11-15 23:26:18 +01006350 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006351 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352
Willy Tarreau62c3be22012-01-20 13:12:32 +01006353 /*
6354 * If this server supports a maxconn parameter, it needs a dedicated
6355 * tasks to fill the emptied slots when a connection leaves.
6356 * Also, resolve deferred tracking dependency if needed.
6357 */
6358 newsrv = curproxy->srv;
6359 while (newsrv != NULL) {
6360 if (newsrv->minconn > newsrv->maxconn) {
6361 /* Only 'minconn' was specified, or it was higher than or equal
6362 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6363 * this will avoid further useless expensive computations.
6364 */
6365 newsrv->maxconn = newsrv->minconn;
6366 } else if (newsrv->maxconn && !newsrv->minconn) {
6367 /* minconn was not specified, so we set it to maxconn */
6368 newsrv->minconn = newsrv->maxconn;
6369 }
6370
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006371#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006372 if (newsrv->use_ssl || newsrv->check.use_ssl)
6373 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006374#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006375
Willy Tarreau62c3be22012-01-20 13:12:32 +01006376 if (newsrv->trackit) {
6377 struct proxy *px;
6378 struct server *srv;
6379 char *pname, *sname;
6380
6381 pname = newsrv->trackit;
6382 sname = strrchr(pname, '/');
6383
6384 if (sname)
6385 *sname++ = '\0';
6386 else {
6387 sname = pname;
6388 pname = NULL;
6389 }
6390
6391 if (pname) {
6392 px = findproxy(pname, PR_CAP_BE);
6393 if (!px) {
6394 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6395 proxy_type_str(curproxy), curproxy->id,
6396 newsrv->id, pname);
6397 cfgerr++;
6398 goto next_srv;
6399 }
6400 } else
6401 px = curproxy;
6402
6403 srv = findserver(px, sname);
6404 if (!srv) {
6405 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6406 proxy_type_str(curproxy), curproxy->id,
6407 newsrv->id, sname);
6408 cfgerr++;
6409 goto next_srv;
6410 }
6411
6412 if (!(srv->state & SRV_CHECKED)) {
6413 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6414 "tracking as it does not have checks enabled.\n",
6415 proxy_type_str(curproxy), curproxy->id,
6416 newsrv->id, px->id, srv->id);
6417 cfgerr++;
6418 goto next_srv;
6419 }
6420
6421 if (curproxy != px &&
6422 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6423 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6424 "tracking: disable-on-404 option inconsistency.\n",
6425 proxy_type_str(curproxy), curproxy->id,
6426 newsrv->id, px->id, srv->id);
6427 cfgerr++;
6428 goto next_srv;
6429 }
6430
6431 /* if the other server is forced disabled, we have to do the same here */
6432 if (srv->state & SRV_MAINTAIN) {
6433 newsrv->state |= SRV_MAINTAIN;
6434 newsrv->state &= ~SRV_RUNNING;
6435 newsrv->health = 0;
6436 }
6437
6438 newsrv->track = srv;
6439 newsrv->tracknext = srv->tracknext;
6440 srv->tracknext = newsrv;
6441
6442 free(newsrv->trackit);
6443 newsrv->trackit = NULL;
6444 }
6445 next_srv:
6446 newsrv = newsrv->next;
6447 }
6448
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006449 /* We have to initialize the server lookup mechanism depending
6450 * on what LB algorithm was choosen.
6451 */
6452
6453 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6454 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6455 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006456 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6457 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6458 init_server_map(curproxy);
6459 } else {
6460 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6461 fwrr_init_server_groups(curproxy);
6462 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006463 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006464
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006465 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006466 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6467 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6468 fwlc_init_server_tree(curproxy);
6469 } else {
6470 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6471 fas_init_server_tree(curproxy);
6472 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006473 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006474
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006475 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006476 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6477 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6478 chash_init_server_tree(curproxy);
6479 } else {
6480 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6481 init_server_map(curproxy);
6482 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006483 break;
6484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485
6486 if (curproxy->options & PR_O_LOGASAP)
6487 curproxy->to_log &= ~LW_BYTES;
6488
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006489 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006490 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006491 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6492 proxy_type_str(curproxy), curproxy->id);
6493 err_code |= ERR_WARN;
6494 }
6495
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006496 if (curproxy->mode != PR_MODE_HTTP) {
6497 int optnum;
6498
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006499 if (curproxy->uri_auth) {
6500 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6501 proxy_type_str(curproxy), curproxy->id);
6502 err_code |= ERR_WARN;
6503 curproxy->uri_auth = NULL;
6504 }
6505
Willy Tarreau87cf5142011-08-19 22:57:24 +02006506 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006507 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6508 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6509 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006510 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006511 }
6512
6513 if (curproxy->options & PR_O_ORGTO) {
6514 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6515 "originalto", proxy_type_str(curproxy), curproxy->id);
6516 err_code |= ERR_WARN;
6517 curproxy->options &= ~PR_O_ORGTO;
6518 }
6519
6520 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6521 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6522 (curproxy->cap & cfg_opts[optnum].cap) &&
6523 (curproxy->options & cfg_opts[optnum].val)) {
6524 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6525 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6526 err_code |= ERR_WARN;
6527 curproxy->options &= ~cfg_opts[optnum].val;
6528 }
6529 }
6530
6531 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6532 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6533 (curproxy->cap & cfg_opts2[optnum].cap) &&
6534 (curproxy->options2 & cfg_opts2[optnum].val)) {
6535 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6536 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6537 err_code |= ERR_WARN;
6538 curproxy->options2 &= ~cfg_opts2[optnum].val;
6539 }
6540 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006541
Willy Tarreauefa5f512010-03-30 20:13:29 +02006542#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006543 if (curproxy->bind_hdr_occ) {
6544 curproxy->bind_hdr_occ = 0;
6545 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6546 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6547 err_code |= ERR_WARN;
6548 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006549#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006550 }
6551
Willy Tarreaubaaee002006-06-26 02:48:02 +02006552 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006553 * ensure that we're not cross-dressing a TCP server into HTTP.
6554 */
6555 newsrv = curproxy->srv;
6556 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006557 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006558 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6559 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006560 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006561 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006562
Willy Tarreau0cec3312011-10-31 13:49:26 +01006563 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6564 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6565 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6566 err_code |= ERR_WARN;
6567 }
6568
Willy Tarreauefa5f512010-03-30 20:13:29 +02006569#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006570 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6571 newsrv->bind_hdr_occ = 0;
6572 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6573 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6574 err_code |= ERR_WARN;
6575 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006576#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006577 newsrv = newsrv->next;
6578 }
6579
Willy Tarreauc1a21672009-08-16 22:37:44 +02006580 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006581 if (!curproxy->accept)
6582 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006583
Willy Tarreauc1a21672009-08-16 22:37:44 +02006584 if (curproxy->tcp_req.inspect_delay ||
6585 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006586 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006587
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006588 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006589 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006590 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006591 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006592
6593 /* both TCP and HTTP must check switching rules */
6594 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6595 }
6596
6597 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006598 if (curproxy->tcp_req.inspect_delay ||
6599 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6600 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6601
Emeric Brun97679e72010-09-23 17:56:44 +02006602 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6603 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6604
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006605 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006606 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006607 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006608 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006609
6610 /* If the backend does requires RDP cookie persistence, we have to
6611 * enable the corresponding analyser.
6612 */
6613 if (curproxy->options2 & PR_O2_RDPC_PRST)
6614 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6615 }
6616
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006617 /* Configure SSL for each bind line.
6618 * Note: if configuration fails at some point, the ->ctx member
6619 * remains NULL so that listeners can later detach.
6620 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006621 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6622 if (!bind_conf->is_ssl)
6623 continue;
6624#ifdef USE_OPENSSL
6625 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006626 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006627 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006628 cfgerr++;
6629 continue;
6630 }
6631
Emeric Brun4b3091e2012-09-24 15:48:52 +02006632 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006633 Alert("Unable to allocate SSL session cache.\n");
6634 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006635 continue;
6636 }
6637
Emeric Brunfc0421f2012-09-07 17:30:07 +02006638 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006639 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006640#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006641 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006642
Willy Tarreaue6b98942007-10-29 01:09:36 +01006643 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006644 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006645 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006646 if (!listener->luid) {
6647 /* listener ID not set, use automatic numbering with first
6648 * spare entry starting with next_luid.
6649 */
6650 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6651 listener->conf.id.key = listener->luid = next_id;
6652 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006653 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006654 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006655
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006656 /* enable separate counters */
6657 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6658 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006659 if (!listener->name)
6660 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006661 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006662
Willy Tarreaue6b98942007-10-29 01:09:36 +01006663 if (curproxy->options & PR_O_TCP_NOLING)
6664 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006665 if (!listener->maxconn)
6666 listener->maxconn = curproxy->maxconn;
6667 if (!listener->backlog)
6668 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006669 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006670 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006671 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006672 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006673
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006674 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6675 listener->options |= LI_O_TCP_RULES;
6676
Willy Tarreaude3041d2010-05-31 10:56:17 +02006677 if (curproxy->mon_mask.s_addr)
6678 listener->options |= LI_O_CHK_MONNET;
6679
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006680 /* smart accept mode is automatic in HTTP mode */
6681 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006682 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006683 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6684 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006685 }
6686
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006687 /* Release unused SSL configs */
6688 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6689 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006690 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006691#ifdef USE_OPENSSL
6692 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006693 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006694 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006695 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006696 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006697#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006698 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006699
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006700 /* Check multi-process mode compatibility for the current proxy */
6701 if (global.nbproc > 1) {
6702 int nbproc = 0;
6703 if (curproxy->bind_proc) {
6704 int proc;
6705 for (proc = 0; proc < global.nbproc; proc++) {
6706 if (curproxy->bind_proc & (1 << proc)) {
6707 nbproc++;
6708 }
6709 }
6710 } else {
6711 nbproc = global.nbproc;
6712 }
6713 if (curproxy->table.peers.name) {
6714 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6715 curproxy->id);
6716 cfgerr++;
6717 }
6718 if (nbproc > 1) {
6719 if (curproxy->uri_auth) {
6720 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6721 curproxy->id);
6722 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6723 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6724 curproxy->id);
6725 }
6726 }
6727 if (curproxy->appsession_name) {
6728 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6729 curproxy->id);
6730 }
6731 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6732 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6733 curproxy->id);
6734 }
6735 }
6736 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006737
6738 /* create the task associated with the proxy */
6739 curproxy->task = task_new();
6740 if (curproxy->task) {
6741 curproxy->task->context = curproxy;
6742 curproxy->task->process = manage_proxy;
6743 /* no need to queue, it will be done automatically if some
6744 * listener gets limited.
6745 */
6746 curproxy->task->expire = TICK_ETERNITY;
6747 } else {
6748 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6749 curproxy->id);
6750 cfgerr++;
6751 }
6752
Willy Tarreaubaaee002006-06-26 02:48:02 +02006753 curproxy = curproxy->next;
6754 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006755
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006756 /* Check multi-process mode compatibility */
6757 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006758 if (global.stats_fe && !global.stats_fe->bind_proc) {
6759 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 +01006760 }
6761 }
6762
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006763 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6764 struct auth_users *curuser;
6765 int g;
6766
6767 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6768 unsigned int group_mask = 0;
6769 char *group = NULL;
6770
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006771 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006772 continue;
6773
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006774 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775
6776 for (g = 0; g < curuserlist->grpcnt; g++)
6777 if (!strcmp(curuserlist->groups[g], group))
6778 break;
6779
6780 if (g == curuserlist->grpcnt) {
6781 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6782 curuserlist->name, group, curuser->user);
6783 err_code |= ERR_ALERT | ERR_FATAL;
6784 goto out;
6785 }
6786
6787 group_mask |= (1 << g);
6788 }
6789
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006790 free(curuser->u.groups);
6791 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006792 }
6793
6794 for (g = 0; g < curuserlist->grpcnt; g++) {
6795 char *user = NULL;
6796
6797 if (!curuserlist->groupusers[g])
6798 continue;
6799
6800 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6801 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6802 if (!strcmp(curuser->user, user))
6803 break;
6804
6805 if (!curuser) {
6806 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6807 curuserlist->name, user, curuserlist->groups[g]);
6808 err_code |= ERR_ALERT | ERR_FATAL;
6809 goto out;
6810 }
6811
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006812 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 }
6814
6815 free(curuserlist->groupusers[g]);
6816 }
6817
6818 free(curuserlist->groupusers);
6819
6820#ifdef DEBUG_AUTH
6821 for (g = 0; g < curuserlist->grpcnt; g++) {
6822 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6823
6824 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006825 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006826 fprintf(stderr, " %s", curuser->user);
6827 }
6828
6829 fprintf(stderr, "\n");
6830 }
6831#endif
6832
Willy Tarreaufbb78422011-06-05 15:38:35 +02006833 }
6834
6835 /* automatically compute fullconn if not set. We must not do it in the
6836 * loop above because cross-references are not yet fully resolved.
6837 */
6838 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6839 /* If <fullconn> is not set, let's set it to 10% of the sum of
6840 * the possible incoming frontend's maxconns.
6841 */
6842 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6843 struct proxy *fe;
6844 int total = 0;
6845
6846 /* sum up the number of maxconns of frontends which
6847 * reference this backend at least once or which are
6848 * the same one ('listen').
6849 */
6850 for (fe = proxy; fe; fe = fe->next) {
6851 struct switching_rule *rule;
6852 struct hdr_exp *exp;
6853 int found = 0;
6854
6855 if (!(fe->cap & PR_CAP_FE))
6856 continue;
6857
6858 if (fe == curproxy) /* we're on a "listen" instance */
6859 found = 1;
6860
6861 if (fe->defbe.be == curproxy) /* "default_backend" */
6862 found = 1;
6863
6864 /* check if a "use_backend" rule matches */
6865 if (!found) {
6866 list_for_each_entry(rule, &fe->switching_rules, list) {
6867 if (rule->be.backend == curproxy) {
6868 found = 1;
6869 break;
6870 }
6871 }
6872 }
6873
6874 /* check if a "reqsetbe" rule matches */
6875 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6876 if (exp->action == ACT_SETBE &&
6877 (struct proxy *)exp->replace == curproxy) {
6878 found = 1;
6879 break;
6880 }
6881 }
6882
6883 /* now we've checked all possible ways to reference a backend
6884 * from a frontend.
6885 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006886 if (!found)
6887 continue;
6888 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006889 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006890 /* we have the sum of the maxconns in <total>. We only
6891 * keep 10% of that sum to set the default fullconn, with
6892 * a hard minimum of 1 (to avoid a divide by zero).
6893 */
6894 curproxy->fullconn = (total + 9) / 10;
6895 if (!curproxy->fullconn)
6896 curproxy->fullconn = 1;
6897 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006898 }
6899
Willy Tarreau056f5682010-06-06 15:51:11 +02006900 /* initialize stick-tables on backend capable proxies. This must not
6901 * be done earlier because the data size may be discovered while parsing
6902 * other proxies.
6903 */
6904 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006905 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006906
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006907 /*
6908 * Recount currently required checks.
6909 */
6910
6911 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6912 int optnum;
6913
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006914 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6915 if (curproxy->options & cfg_opts[optnum].val)
6916 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006917
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006918 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6919 if (curproxy->options2 & cfg_opts2[optnum].val)
6920 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006921 }
6922
Willy Tarreau122541c2011-09-07 21:24:49 +02006923 if (peers) {
6924 struct peers *curpeers = peers, **last;
6925 struct peer *p, *pb;
6926
6927 /* Remove all peers sections which don't have a valid listener.
6928 * This can happen when a peers section is never referenced and
6929 * does not contain a local peer.
6930 */
6931 last = &peers;
6932 while (*last) {
6933 curpeers = *last;
6934 if (curpeers->peers_fe) {
6935 last = &curpeers->next;
6936 continue;
6937 }
6938
6939 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6940 curpeers->id, localpeer);
6941
6942 p = curpeers->remote;
6943 while (p) {
6944 pb = p->next;
6945 free(p->id);
6946 free(p);
6947 p = pb;
6948 }
6949
6950 /* Destroy and unlink this curpeers section.
6951 * Note: curpeers is backed up into *last.
6952 */
6953 free(curpeers->id);
6954 curpeers = curpeers->next;
6955 free(*last);
6956 *last = curpeers;
6957 }
6958 }
6959
Willy Tarreauac1932d2011-10-24 19:14:41 +02006960 if (!global.tune.max_http_hdr)
6961 global.tune.max_http_hdr = MAX_HTTP_HDR;
6962
Willy Tarreau34eb6712011-10-24 18:15:04 +02006963 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006964 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006965 MEM_F_SHARED);
6966
Willy Tarreaubb925012009-07-23 13:36:36 +02006967 if (cfgerr > 0)
6968 err_code |= ERR_ALERT | ERR_FATAL;
6969 out:
6970 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971}
6972
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006973/*
6974 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6975 * parsing sessions.
6976 */
6977void cfg_register_keywords(struct cfg_kw_list *kwl)
6978{
6979 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6980}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006981
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006982/*
6983 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6984 */
6985void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6986{
6987 LIST_DEL(&kwl->list);
6988 LIST_INIT(&kwl->list);
6989}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990
6991/*
6992 * Local variables:
6993 * c-indent-level: 8
6994 * c-basic-offset: 8
6995 * End:
6996 */