blob: 971371d18a05d44d2605357f1a2736eabb6d5513 [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 Tarreauc919dc62012-10-26 17:35:22 +0200585 trash = realloc(trash, global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200586 }
587 else if (!strcmp(args[0], "tune.maxrewrite")) {
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
592 }
593 global.tune.maxrewrite = atol(args[1]);
594 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
595 global.tune.maxrewrite = global.tune.bufsize / 2;
596 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100597 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
598 if (global.tune.client_rcvbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.client_rcvbuf = atol(args[1]);
609 }
610 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
611 if (global.tune.server_rcvbuf != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.server_rcvbuf = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "tune.sndbuf.client")) {
624 if (global.tune.client_sndbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_sndbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.sndbuf.server")) {
637 if (global.tune.server_sndbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_sndbuf = atol(args[1]);
648 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200649 else if (!strcmp(args[0], "tune.pipesize")) {
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.pipesize = atol(args[1]);
656 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200657 else if (!strcmp(args[0], "tune.http.maxhdr")) {
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
662 }
663 global.tune.max_http_hdr = atol(args[1]);
664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 else if (!strcmp(args[0], "uid")) {
666 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.uid = atol(args[1]);
677 }
678 else if (!strcmp(args[0], "gid")) {
679 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200680 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 if (*(args[1]) == 0) {
685 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT | ERR_FATAL;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 global.gid = atol(args[1]);
690 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200691 /* user/group name handling */
692 else if (!strcmp(args[0], "user")) {
693 struct passwd *ha_user;
694 if (global.uid != 0) {
695 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200698 }
699 errno = 0;
700 ha_user = getpwnam(args[1]);
701 if (ha_user != NULL) {
702 global.uid = (int)ha_user->pw_uid;
703 }
704 else {
705 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200707 }
708 }
709 else if (!strcmp(args[0], "group")) {
710 struct group *ha_group;
711 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200712 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT;
714 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200715 }
716 errno = 0;
717 ha_group = getgrnam(args[1]);
718 if (ha_group != NULL) {
719 global.gid = (int)ha_group->gr_gid;
720 }
721 else {
722 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200724 }
725 }
726 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 else if (!strcmp(args[0], "nbproc")) {
728 if (global.nbproc != 0) {
729 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733 if (*(args[1]) == 0) {
734 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 }
738 global.nbproc = atol(args[1]);
739 }
740 else if (!strcmp(args[0], "maxconn")) {
741 if (global.maxconn != 0) {
742 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT;
744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 }
751 global.maxconn = atol(args[1]);
752#ifdef SYSTEM_MAXCONN
753 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
754 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
755 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758#endif /* SYSTEM_MAXCONN */
759 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200760 else if (!strcmp(args[0], "maxsslconn")) {
761#ifdef USE_OPENSSL
762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.maxsslconn = atol(args[1]);
768#else
Emeric Brun0914df82012-10-02 18:45:42 +0200769 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
770 err_code |= ERR_ALERT | ERR_FATAL;
771 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200772#endif
773 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200774 else if (!strcmp(args[0], "maxconnrate")) {
775 if (global.cps_lim != 0) {
776 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT;
778 goto out;
779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 global.cps_lim = atol(args[1]);
786 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100787 else if (!strcmp(args[0], "maxpipes")) {
788 if (global.maxpipes != 0) {
789 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100792 }
793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100797 }
798 global.maxpipes = atol(args[1]);
799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 else if (!strcmp(args[0], "ulimit-n")) {
801 if (global.rlimit_nofile != 0) {
802 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200810 }
811 global.rlimit_nofile = atol(args[1]);
812 }
813 else if (!strcmp(args[0], "chroot")) {
814 if (global.chroot != NULL) {
815 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200816 err_code |= ERR_ALERT;
817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 }
824 global.chroot = strdup(args[1]);
825 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200826 else if (!strcmp(args[0], "description")) {
827 int i, len=0;
828 char *d;
829
830 if (!*args[1]) {
831 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
832 file, linenum, args[0]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 for(i=1; *args[i]; i++)
838 len += strlen(args[i])+1;
839
840 if (global.desc)
841 free(global.desc);
842
843 global.desc = d = (char *)calloc(1, len);
844
845 d += sprintf(d, "%s", args[1]);
846 for(i=2; *args[i]; i++)
847 d += sprintf(d, " %s", args[i]);
848 }
849 else if (!strcmp(args[0], "node")) {
850 int i;
851 char c;
852
853 for (i=0; args[1][i]; i++) {
854 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100855 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
856 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200857 break;
858 }
859
860 if (!i || args[1][i]) {
861 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
862 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
863 file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 if (global.node)
869 free(global.node);
870
871 global.node = strdup(args[1]);
872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 else if (!strcmp(args[0], "pidfile")) {
874 if (global.pidfile != NULL) {
875 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200876 err_code |= ERR_ALERT;
877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 }
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883 }
884 global.pidfile = strdup(args[1]);
885 }
Emeric Bruned760922010-10-22 17:59:25 +0200886 else if (!strcmp(args[0], "unix-bind")) {
887 int cur_arg = 1;
888 while (*(args[cur_arg])) {
889 if (!strcmp(args[cur_arg], "prefix")) {
890 if (global.unix_bind.prefix != NULL) {
891 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
892 err_code |= ERR_ALERT;
893 cur_arg += 2;
894 continue;
895 }
896
897 if (*(args[cur_arg+1]) == 0) {
898 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.unix_bind.prefix = strdup(args[cur_arg+1]);
903 cur_arg += 2;
904 continue;
905 }
906
907 if (!strcmp(args[cur_arg], "mode")) {
908
909 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
910 cur_arg += 2;
911 continue;
912 }
913
914 if (!strcmp(args[cur_arg], "uid")) {
915
916 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
917 cur_arg += 2;
918 continue;
919 }
920
921 if (!strcmp(args[cur_arg], "gid")) {
922
923 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
924 cur_arg += 2;
925 continue;
926 }
927
928 if (!strcmp(args[cur_arg], "user")) {
929 struct passwd *user;
930
931 user = getpwnam(args[cur_arg + 1]);
932 if (!user) {
933 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
934 file, linenum, args[0], args[cur_arg + 1 ]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
938
939 global.unix_bind.ux.uid = user->pw_uid;
940 cur_arg += 2;
941 continue;
942 }
943
944 if (!strcmp(args[cur_arg], "group")) {
945 struct group *group;
946
947 group = getgrnam(args[cur_arg + 1]);
948 if (!group) {
949 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
950 file, linenum, args[0], args[cur_arg + 1 ]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954
955 global.unix_bind.ux.gid = group->gr_gid;
956 cur_arg += 2;
957 continue;
958 }
959
Willy Tarreaub48f9582011-09-05 01:17:06 +0200960 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200961 file, linenum, args[0]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 }
William Lallemand0f99e342011-10-12 17:50:54 +0200966 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
967 /* delete previous herited or defined syslog servers */
968 struct logsrv *back;
969 struct logsrv *tmp;
970
971 if (*(args[1]) != 0) {
972 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
976
977 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
978 LIST_DEL(&tmp->list);
979 free(tmp);
980 }
981 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200983 struct logsrv *logsrv;
984
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 if (*(args[1]) == 0 || *(args[2]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 }
William Lallemand0f99e342011-10-12 17:50:54 +0200990
991 logsrv = calloc(1, sizeof(struct logsrv));
992
993 logsrv->facility = get_log_facility(args[2]);
994 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200997 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999
William Lallemand0f99e342011-10-12 17:50:54 +02001000 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001002 logsrv->level = get_log_level(args[3]);
1003 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001006 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 }
1009
William Lallemand0f99e342011-10-12 17:50:54 +02001010 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001011 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001012 logsrv->minlvl = get_log_level(args[4]);
1013 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001014 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001016 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001017 }
1018 }
1019
Robert Tsai81ae1952007-12-05 10:47:29 +01001020 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001021 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001022 if (!sk) {
1023 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001024 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001025 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001026 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001027 goto out;
1028 }
William Lallemand0f99e342011-10-12 17:50:54 +02001029 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001030 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001031 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001032 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001033 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001035 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001036 goto out;
1037 }
William Lallemand0f99e342011-10-12 17:50:54 +02001038 logsrv->addr = *sk;
1039 if (!get_host_port(&logsrv->addr))
1040 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042
William Lallemand0f99e342011-10-12 17:50:54 +02001043 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001044 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001045 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1046 char *name;
1047 int len;
1048
1049 if (global.log_send_hostname != NULL) {
1050 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT;
1052 goto out;
1053 }
1054
1055 if (*(args[1]))
1056 name = args[1];
1057 else
1058 name = hostname;
1059
1060 len = strlen(name);
1061
1062 /* We'll add a space after the name to respect the log format */
1063 free(global.log_send_hostname);
1064 global.log_send_hostname = malloc(len + 2);
1065 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1066 }
Kevinm48936af2010-12-22 16:08:21 +00001067 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 free(global.log_tag);
1074 global.log_tag = strdup(args[1]);
1075 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001076 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1077 if (global.spread_checks != 0) {
1078 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001079 err_code |= ERR_ALERT;
1080 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001081 }
1082 if (*(args[1]) == 0) {
1083 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001084 err_code |= ERR_ALERT | ERR_FATAL;
1085 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001086 }
1087 global.spread_checks = atol(args[1]);
1088 if (global.spread_checks < 0 || global.spread_checks > 50) {
1089 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001094 struct cfg_kw_list *kwl;
1095 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001096 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001097
1098 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1099 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1100 if (kwl->kw[index].section != CFG_GLOBAL)
1101 continue;
1102 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1103 /* prepare error message just in case */
Willy Tarreauc919dc62012-10-26 17:35:22 +02001104 snprintf(trash, global.tune.bufsize,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001105 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau28a47d62012-09-18 20:02:48 +02001106 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001107 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001108 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001109 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001110 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001111 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001112 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001113 err_code |= ERR_WARN;
1114 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001115 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001116 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001117 }
1118 }
1119 }
1120
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001124
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001126 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001127 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128}
1129
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001130void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001132 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 defproxy.mode = PR_MODE_TCP;
1134 defproxy.state = PR_STNEW;
1135 defproxy.maxconn = cfg_maxpconn;
1136 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001137
1138 defproxy.defsrv.inter = DEF_CHKINTR;
1139 defproxy.defsrv.fastinter = 0;
1140 defproxy.defsrv.downinter = 0;
1141 defproxy.defsrv.rise = DEF_RISETIME;
1142 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001143 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001144 defproxy.defsrv.maxqueue = 0;
1145 defproxy.defsrv.minconn = 0;
1146 defproxy.defsrv.maxconn = 0;
1147 defproxy.defsrv.slowstart = 0;
1148 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1149 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1150 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151}
1152
Willy Tarreauade5ec42010-01-28 19:33:49 +01001153
1154static int create_cond_regex_rule(const char *file, int line,
1155 struct proxy *px, int dir, int action, int flags,
1156 const char *cmd, const char *reg, const char *repl,
1157 const char **cond_start)
1158{
1159 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001160 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001161 const char *err;
1162 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001163 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001164
1165 if (px == &defproxy) {
1166 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto err;
1169 }
1170
1171 if (*reg == 0) {
1172 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1173 err_code |= ERR_ALERT | ERR_FATAL;
1174 goto err;
1175 }
1176
1177 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1178 err_code |= ERR_WARN;
1179
Willy Tarreau5321c422010-01-28 20:35:13 +01001180 if (cond_start &&
1181 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001182 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1183 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1184 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto err;
1187 }
1188 }
1189 else if (cond_start && **cond_start) {
1190 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1191 file, line, cmd, *cond_start);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto err;
1194 }
1195
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001196 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001197 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001198 else
1199 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001200
Willy Tarreauade5ec42010-01-28 19:33:49 +01001201 preg = calloc(1, sizeof(regex_t));
1202 if (!preg) {
1203 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1204 err_code = ERR_ALERT | ERR_FATAL;
1205 goto err;
1206 }
1207
1208 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1209 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1210 err_code = ERR_ALERT | ERR_FATAL;
1211 goto err;
1212 }
1213
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001214 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001215 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001216 if (repl && err) {
1217 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1218 file, line, cmd, *err);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto err;
1221 }
1222
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001223 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001224 err_code |= ERR_WARN;
1225
Willy Tarreauf4068b62012-05-08 17:37:49 +02001226 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001227 return err_code;
1228 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001229 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001230 free(preg);
1231 return err_code;
1232}
1233
Willy Tarreaubaaee002006-06-26 02:48:02 +02001234/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001235 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001236 * Returns the error code, 0 if OK, or any combination of :
1237 * - ERR_ABORT: must abort ASAP
1238 * - ERR_FATAL: we can continue parsing but not start the service
1239 * - ERR_WARN: a warning has been emitted
1240 * - ERR_ALERT: an alert has been emitted
1241 * Only the two first ones can stop processing, the two others are just
1242 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001243 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001244int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1245{
1246 static struct peers *curpeers = NULL;
1247 struct peer *newpeer = NULL;
1248 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001249 struct bind_conf *bind_conf;
1250 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001251 int err_code = 0;
1252
1253 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1254
1255 err = invalid_char(args[1]);
1256 if (err) {
1257 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1258 file, linenum, *err, args[0], args[1]);
1259 err_code |= ERR_ALERT | ERR_FATAL;
1260 }
1261
1262 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1263 /*
1264 * If there are two proxies with the same name only following
1265 * combinations are allowed:
1266 */
1267 if (strcmp(curpeers->id, args[1]) == 0) {
1268 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1269 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1270 err_code |= ERR_WARN;
1271 }
1272 }
1273
1274 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1276 err_code |= ERR_ALERT | ERR_ABORT;
1277 goto out;
1278 }
1279
1280 curpeers->next = peers;
1281 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001282 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001283 curpeers->conf.line = linenum;
1284 curpeers->last_change = now.tv_sec;
1285 curpeers->id = strdup(args[1]);
1286 }
1287 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1288 char *rport, *raddr;
1289 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001290 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001291 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001292
1293 if (!*args[2]) {
1294 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1295 file, linenum, args[0]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
1300 err = invalid_char(args[1]);
1301 if (err) {
1302 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1303 file, linenum, *err, args[1]);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307
1308 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1310 err_code |= ERR_ALERT | ERR_ABORT;
1311 goto out;
1312 }
1313
1314 /* the peers are linked backwards first */
1315 curpeers->count++;
1316 newpeer->next = curpeers->remote;
1317 curpeers->remote = newpeer;
1318 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001319 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001320 newpeer->conf.line = linenum;
1321
1322 newpeer->last_change = now.tv_sec;
1323 newpeer->id = strdup(args[1]);
1324
1325 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001326 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001327 if (rport) {
1328 *rport++ = 0;
1329 realport = atol(rport);
1330 }
1331 if (!realport) {
1332 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1333 err_code |= ERR_ALERT | ERR_FATAL;
1334 goto out;
1335 }
1336
Willy Tarreaufab5a432011-03-04 15:31:53 +01001337 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001338 free(raddr);
1339 if (!sk) {
1340 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
1343 }
1344 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001345 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001346 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001347 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001348
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001349 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001350 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1351 file, linenum, newpeer->addr.ss_family, args[2]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001356 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001357
1358 if (strcmp(newpeer->id, localpeer) == 0) {
1359 /* Current is local peer, it define a frontend */
1360 newpeer->local = 1;
1361
1362 if (!curpeers->peers_fe) {
1363 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1364 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1365 err_code |= ERR_ALERT | ERR_ABORT;
1366 goto out;
1367 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001368
Willy Tarreau237250c2011-07-29 01:49:03 +02001369 init_new_proxy(curpeers->peers_fe);
1370 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001371
1372 curpeers->peers_fe->last_change = now.tv_sec;
1373 curpeers->peers_fe->id = strdup(args[1]);
1374 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001375 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001376 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1377 curpeers->peers_fe->timeout.connect = 5000;
1378 curpeers->peers_fe->accept = peer_accept;
1379 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001380
1381 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1382
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001383 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1384 if (err_msg && *err_msg) {
1385 indent_msg(&err_msg, 2);
1386 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1387 }
1388 else
1389 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1390 file, linenum, args[0], args[1], args[2]);
1391 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001392 err_code |= ERR_FATAL;
1393 goto out;
1394 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001395
1396 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1397 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1398 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1399 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1400 l->accept = session_accept;
1401 l->handler = process_session;
1402 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1403 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1404 global.maxsock += l->maxconn;
1405 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001406 }
1407 }
1408 } /* neither "peer" nor "peers" */
1409 else if (*args[0] != 0) {
1410 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414
1415out:
1416 return err_code;
1417}
1418
1419
Willy Tarreau3842f002009-06-14 11:39:52 +02001420int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421{
1422 static struct proxy *curproxy = NULL;
1423 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001424 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001425 int rc;
1426 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001427 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001428 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001429 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001430 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001431 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432
Willy Tarreau977b8e42006-12-29 14:19:17 +01001433 if (!strcmp(args[0], "listen"))
1434 rc = PR_CAP_LISTEN;
1435 else if (!strcmp(args[0], "frontend"))
1436 rc = PR_CAP_FE | PR_CAP_RS;
1437 else if (!strcmp(args[0], "backend"))
1438 rc = PR_CAP_BE | PR_CAP_RS;
1439 else if (!strcmp(args[0], "ruleset"))
1440 rc = PR_CAP_RS;
1441 else
1442 rc = PR_CAP_NONE;
1443
1444 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 if (!*args[1]) {
1446 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1447 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001449 err_code |= ERR_ALERT | ERR_ABORT;
1450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001452
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001453 err = invalid_char(args[1]);
1454 if (err) {
1455 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1456 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001458 }
1459
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001460 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1461 /*
1462 * If there are two proxies with the same name only following
1463 * combinations are allowed:
1464 *
1465 * listen backend frontend ruleset
1466 * listen - - - -
1467 * backend - - OK -
1468 * frontend - OK - -
1469 * ruleset - - - -
1470 */
1471
1472 if (!strcmp(curproxy->id, args[1]) &&
1473 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1474 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001475 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1476 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1477 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001478 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001479 }
1480 }
1481
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1483 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001484 err_code |= ERR_ALERT | ERR_ABORT;
1485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001486 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001487
Willy Tarreau97cb7802010-01-03 20:23:58 +01001488 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 curproxy->next = proxy;
1490 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001491 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001492 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001493 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496
1497 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001499 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001500 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001501
Willy Tarreau4348fad2012-09-20 16:48:07 +02001502 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1503
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001504 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1505 if (err_msg && *err_msg) {
1506 indent_msg(&err_msg, 2);
1507 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1508 }
1509 else
1510 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1511 file, linenum, args[0], args[1], args[2]);
1512 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001513 err_code |= ERR_FATAL;
1514 goto out;
1515 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001516
Willy Tarreau4348fad2012-09-20 16:48:07 +02001517 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001518 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 }
1521
1522 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001523 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001524 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001525
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001528 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001529 curproxy->no_options = defproxy.no_options;
1530 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001531 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001532 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001533 curproxy->except_net = defproxy.except_net;
1534 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001535 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001536 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001538 if (defproxy.fwdfor_hdr_len) {
1539 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1540 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1541 }
1542
Willy Tarreaub86db342009-11-30 11:50:16 +01001543 if (defproxy.orgto_hdr_len) {
1544 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1545 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1546 }
1547
Mark Lamourinec2247f02012-01-04 13:02:01 -05001548 if (defproxy.server_id_hdr_len) {
1549 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1550 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1551 }
1552
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 if (curproxy->cap & PR_CAP_FE) {
1554 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001555 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001556 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557
1558 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001559 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1560 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001561
1562 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1563 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 if (curproxy->cap & PR_CAP_BE) {
1566 curproxy->fullconn = defproxy.fullconn;
1567 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001569 if (defproxy.check_req) {
1570 curproxy->check_req = calloc(1, defproxy.check_len);
1571 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1572 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001573 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001575 if (defproxy.expect_str) {
1576 curproxy->expect_str = strdup(defproxy.expect_str);
1577 if (defproxy.expect_regex) {
1578 /* note: this regex is known to be valid */
1579 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1580 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1581 }
1582 }
1583
Willy Tarreau67402132012-05-31 20:40:20 +02001584 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 if (defproxy.cookie_name)
1586 curproxy->cookie_name = strdup(defproxy.cookie_name);
1587 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001588 if (defproxy.cookie_domain)
1589 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001590
Willy Tarreau31936852010-10-06 16:59:56 +02001591 if (defproxy.cookie_maxidle)
1592 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1593
1594 if (defproxy.cookie_maxlife)
1595 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1596
Emeric Brun647caf12009-06-30 17:57:00 +02001597 if (defproxy.rdp_cookie_name)
1598 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1599 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1600
Willy Tarreau01732802007-11-01 22:48:15 +01001601 if (defproxy.url_param_name)
1602 curproxy->url_param_name = strdup(defproxy.url_param_name);
1603 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001604
Benoitaffb4812009-03-25 13:02:10 +01001605 if (defproxy.hh_name)
1606 curproxy->hh_name = strdup(defproxy.hh_name);
1607 curproxy->hh_len = defproxy.hh_len;
1608 curproxy->hh_match_domain = defproxy.hh_match_domain;
1609
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001610 if (defproxy.iface_name)
1611 curproxy->iface_name = strdup(defproxy.iface_name);
1612 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001615 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001616 if (defproxy.capture_name)
1617 curproxy->capture_name = strdup(defproxy.capture_name);
1618 curproxy->capture_namelen = defproxy.capture_namelen;
1619 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621
Willy Tarreau977b8e42006-12-29 14:19:17 +01001622 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001623 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001624 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001625 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001626 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627 curproxy->uri_auth = defproxy.uri_auth;
1628 curproxy->mon_net = defproxy.mon_net;
1629 curproxy->mon_mask = defproxy.mon_mask;
1630 if (defproxy.monitor_uri)
1631 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1632 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001633 if (defproxy.defbe.name)
1634 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001635
1636 /* get either a pointer to the logformat string or a copy of it */
1637 curproxy->logformat_string = defproxy.logformat_string;
1638 if (curproxy->logformat_string &&
1639 curproxy->logformat_string != default_http_log_format &&
1640 curproxy->logformat_string != default_tcp_log_format &&
1641 curproxy->logformat_string != clf_http_log_format)
1642 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001643 }
1644
1645 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001646 curproxy->timeout.connect = defproxy.timeout.connect;
1647 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001648 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001649 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001650 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001651 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001652 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001653 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654 curproxy->source_addr = defproxy.source_addr;
1655 }
1656
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001658
1659 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001660 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001661 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001662 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001663 LIST_INIT(&node->list);
1664 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1665 }
1666
Willy Tarreau196729e2012-05-31 19:30:26 +02001667 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1668 if (curproxy->uniqueid_format_string)
1669 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001670
1671 /* copy default header unique id */
1672 if (defproxy.header_unique_id)
1673 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1674
William Lallemand82fe75c2012-10-23 10:25:10 +02001675 /* default compression options */
1676 if (defproxy.comp != NULL) {
1677 curproxy->comp = calloc(1, sizeof(struct comp));
1678 curproxy->comp->algos = defproxy.comp->algos;
1679 curproxy->comp->types = defproxy.comp->types;
1680 }
1681
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001683 curproxy->conf.used_listener_id = EB_ROOT;
1684 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001685
Willy Tarreau93893792009-07-23 13:19:11 +02001686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687 }
1688 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1689 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001690 /* FIXME-20070101: we should do this too at the end of the
1691 * config parsing to free all default values.
1692 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001693 free(defproxy.check_req);
1694 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001695 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001696 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001697 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001698 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001699 free(defproxy.capture_name);
1700 free(defproxy.monitor_uri);
1701 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001702 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001703 free(defproxy.fwdfor_hdr_name);
1704 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001705 free(defproxy.orgto_hdr_name);
1706 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001707 free(defproxy.server_id_hdr_name);
1708 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001709 free(defproxy.expect_str);
1710 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001711
Willy Tarreau39b06652012-06-01 10:58:06 +02001712 if (defproxy.logformat_string != default_http_log_format &&
1713 defproxy.logformat_string != default_tcp_log_format &&
1714 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001715 free(defproxy.logformat_string);
1716
1717 free(defproxy.uniqueid_format_string);
1718
Willy Tarreaua534fea2008-08-03 12:19:50 +02001719 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001720 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001721
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 /* we cannot free uri_auth because it might already be used */
1723 init_default_instance();
1724 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001725 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 }
1728 else if (curproxy == NULL) {
1729 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 }
1733
Willy Tarreau977b8e42006-12-29 14:19:17 +01001734
1735 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001737 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001738 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001739 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001740
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 if (curproxy == &defproxy) {
1742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001747 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748
Emeric Bruned760922010-10-22 17:59:25 +02001749 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001750 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001755
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001756 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001757 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001758
1759 /* NOTE: the following line might create several listeners if there
1760 * are comma-separated IPs or port ranges. So all further processing
1761 * will have to be applied to all listeners created after last_listen.
1762 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001763 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1764 if (err_msg && *err_msg) {
1765 indent_msg(&err_msg, 2);
1766 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1767 }
1768 else
1769 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1770 file, linenum, args[0], args[1]);
1771 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001775
Willy Tarreau4348fad2012-09-20 16:48:07 +02001776 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1777 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001778 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001779 }
1780
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001781 cur_arg = 2;
1782 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001783 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001784 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001785 char *err;
1786
Willy Tarreau26982662012-09-12 23:17:10 +02001787 kw = bind_find_kw(args[cur_arg]);
1788 if (kw) {
1789 char *err = NULL;
1790 int code;
1791
1792 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001793 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1794 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001795 cur_arg += 1 + kw->skip ;
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
1799
Willy Tarreau4348fad2012-09-20 16:48:07 +02001800 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001801 err_code |= code;
1802
1803 if (code) {
1804 if (err && *err) {
1805 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001806 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001807 }
1808 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001809 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1810 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001811 if (code & ERR_FATAL) {
1812 free(err);
1813 cur_arg += 1 + kw->skip;
1814 goto out;
1815 }
1816 }
1817 free(err);
1818 cur_arg += 1 + kw->skip;
1819 continue;
1820 }
1821
Willy Tarreau8638f482012-09-18 18:01:17 +02001822 err = NULL;
1823 if (!bind_dumped) {
1824 bind_dump_kws(&err);
1825 indent_msg(&err, 4);
1826 bind_dumped = 1;
1827 }
1828
1829 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1830 file, linenum, args[0], args[1], args[cur_arg],
1831 err ? " Registered keywords :" : "", err ? err : "");
1832 free(err);
1833
Willy Tarreau93893792009-07-23 13:19:11 +02001834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001836 }
Willy Tarreau93893792009-07-23 13:19:11 +02001837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838 }
1839 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1840 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1841 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001846 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001847 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001848
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 /* flush useless bits */
1850 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001853 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001854 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001855 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001856
Willy Tarreau1c47f852006-07-09 08:22:27 +02001857 if (!*args[1]) {
1858 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001860 err_code |= ERR_ALERT | ERR_FATAL;
1861 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001862 }
1863
Willy Tarreaua534fea2008-08-03 12:19:50 +02001864 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001865 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001866 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001867 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001868 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1869
Willy Tarreau93893792009-07-23 13:19:11 +02001870 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1873 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1874 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1875 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1876 else {
1877 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 }
1881 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001882 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001883 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001884
1885 if (curproxy == &defproxy) {
1886 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001890 }
1891
1892 if (!*args[1]) {
1893 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001897 }
1898
1899 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001900 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001901
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001902 if (curproxy->uuid <= 0) {
1903 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001904 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001907 }
1908
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001909 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1910 if (node) {
1911 struct proxy *target = container_of(node, struct proxy, conf.id);
1912 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1913 file, linenum, proxy_type_str(curproxy), curproxy->id,
1914 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
1917 }
1918 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001919 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001920 else if (!strcmp(args[0], "description")) {
1921 int i, len=0;
1922 char *d;
1923
Cyril Bonté99ed3272010-01-24 23:29:44 +01001924 if (curproxy == &defproxy) {
1925 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1926 file, linenum, args[0]);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001931 if (!*args[1]) {
1932 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1933 file, linenum, args[0]);
1934 return -1;
1935 }
1936
1937 for(i=1; *args[i]; i++)
1938 len += strlen(args[i])+1;
1939
1940 d = (char *)calloc(1, len);
1941 curproxy->desc = d;
1942
1943 d += sprintf(d, "%s", args[1]);
1944 for(i=2; *args[i]; i++)
1945 d += sprintf(d, " %s", args[i]);
1946
1947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1949 curproxy->state = PR_STSTOPPED;
1950 }
1951 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1952 curproxy->state = PR_STNEW;
1953 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001954 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1955 int cur_arg = 1;
1956 unsigned int set = 0;
1957
1958 while (*args[cur_arg]) {
1959 int u;
1960 if (strcmp(args[cur_arg], "all") == 0) {
1961 set = 0;
1962 break;
1963 }
1964 else if (strcmp(args[cur_arg], "odd") == 0) {
1965 set |= 0x55555555;
1966 }
1967 else if (strcmp(args[cur_arg], "even") == 0) {
1968 set |= 0xAAAAAAAA;
1969 }
1970 else {
1971 u = str2uic(args[cur_arg]);
1972 if (u < 1 || u > 32) {
1973 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001977 }
1978 if (u > global.nbproc) {
1979 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1980 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001982 }
1983 set |= 1 << (u - 1);
1984 }
1985 cur_arg++;
1986 }
1987 curproxy->bind_proc = set;
1988 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001989 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001990 if (curproxy == &defproxy) {
1991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001994 }
1995
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001996 err = invalid_char(args[1]);
1997 if (err) {
1998 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1999 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002001 }
2002
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002003 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2004 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2005 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_ALERT | ERR_FATAL;
2007 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002008 }
2009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2011 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012
Willy Tarreau977b8e42006-12-29 14:19:17 +01002013 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002014 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002015
Willy Tarreaubaaee002006-06-26 02:48:02 +02002016 if (*(args[1]) == 0) {
2017 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002022
Willy Tarreau67402132012-05-31 20:40:20 +02002023 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002024 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002025 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002026 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 curproxy->cookie_name = strdup(args[1]);
2028 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002029
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 cur_arg = 2;
2031 while (*(args[cur_arg])) {
2032 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002033 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 }
2035 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002036 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 }
2038 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002039 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 }
2041 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002042 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 }
2044 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002045 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002046 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002047 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002048 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002051 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002053 else if (!strcmp(args[cur_arg], "httponly")) {
2054 curproxy->ck_opts |= PR_CK_HTTPONLY;
2055 }
2056 else if (!strcmp(args[cur_arg], "secure")) {
2057 curproxy->ck_opts |= PR_CK_SECURE;
2058 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002059 else if (!strcmp(args[cur_arg], "domain")) {
2060 if (!*args[cur_arg + 1]) {
2061 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2062 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002065 }
2066
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002067 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002068 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002069 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2070 " dots nor does not start with a dot."
2071 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002072 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002073 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002074 }
2075
2076 err = invalid_domainchar(args[cur_arg + 1]);
2077 if (err) {
2078 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2079 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002082 }
2083
Willy Tarreau68a897b2009-12-03 23:28:34 +01002084 if (!curproxy->cookie_domain) {
2085 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2086 } else {
2087 /* one domain was already specified, add another one by
2088 * building the string which will be returned along with
2089 * the cookie.
2090 */
2091 char *new_ptr;
2092 int new_len = strlen(curproxy->cookie_domain) +
2093 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2094 new_ptr = malloc(new_len);
2095 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2096 free(curproxy->cookie_domain);
2097 curproxy->cookie_domain = new_ptr;
2098 }
Willy Tarreau31936852010-10-06 16:59:56 +02002099 cur_arg++;
2100 }
2101 else if (!strcmp(args[cur_arg], "maxidle")) {
2102 unsigned int maxidle;
2103 const char *res;
2104
2105 if (!*args[cur_arg + 1]) {
2106 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2107 file, linenum, args[cur_arg]);
2108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
2110 }
2111
2112 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2113 if (res) {
2114 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2115 file, linenum, *res, args[cur_arg]);
2116 err_code |= ERR_ALERT | ERR_FATAL;
2117 goto out;
2118 }
2119 curproxy->cookie_maxidle = maxidle;
2120 cur_arg++;
2121 }
2122 else if (!strcmp(args[cur_arg], "maxlife")) {
2123 unsigned int maxlife;
2124 const char *res;
2125
2126 if (!*args[cur_arg + 1]) {
2127 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2128 file, linenum, args[cur_arg]);
2129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
2131 }
2132
2133 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2134 if (res) {
2135 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2136 file, linenum, *res, args[cur_arg]);
2137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
2139 }
2140 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002141 cur_arg++;
2142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002144 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 +02002145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 }
2149 cur_arg++;
2150 }
Willy Tarreau67402132012-05-31 20:40:20 +02002151 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2153 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 }
2156
Willy Tarreau67402132012-05-31 20:40:20 +02002157 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2159 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002160 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002162
Willy Tarreau67402132012-05-31 20:40:20 +02002163 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002164 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2165 file, linenum);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002168 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002169 else if (!strcmp(args[0], "persist")) { /* persist */
2170 if (*(args[1]) == 0) {
2171 Alert("parsing [%s:%d] : missing persist method.\n",
2172 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002173 err_code |= ERR_ALERT | ERR_FATAL;
2174 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002175 }
2176
2177 if (!strncmp(args[1], "rdp-cookie", 10)) {
2178 curproxy->options2 |= PR_O2_RDPC_PRST;
2179
Emeric Brunb982a3d2010-01-04 15:45:53 +01002180 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002181 const char *beg, *end;
2182
2183 beg = args[1] + 11;
2184 end = strchr(beg, ')');
2185
2186 if (!end || end == beg) {
2187 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2188 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002191 }
2192
2193 free(curproxy->rdp_cookie_name);
2194 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2195 curproxy->rdp_cookie_len = end-beg;
2196 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002197 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002198 free(curproxy->rdp_cookie_name);
2199 curproxy->rdp_cookie_name = strdup("msts");
2200 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2201 }
2202 else { /* syntax */
2203 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2204 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002207 }
2208 }
2209 else {
2210 Alert("parsing [%s:%d] : unknown persist method.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002214 }
2215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002217 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002219 if (curproxy == &defproxy) {
2220 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002227
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002229 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002231 err_code |= ERR_ALERT | ERR_FATAL;
2232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 }
2234 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 curproxy->appsession_name = strdup(args[1]);
2237 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2238 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002239 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2240 if (err) {
2241 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2242 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002245 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002246 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002247
Willy Tarreau51041c72007-09-09 21:56:53 +02002248 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_ABORT;
2251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002253
2254 cur_arg = 6;
2255 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002256 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2257 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002258 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002259 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002260 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002261 } else if (!strcmp(args[cur_arg], "prefix")) {
2262 curproxy->options2 |= PR_O2_AS_PFX;
2263 } else if (!strcmp(args[cur_arg], "mode")) {
2264 if (!*args[cur_arg + 1]) {
2265 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2266 file, linenum, args[0], args[cur_arg]);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270
2271 cur_arg++;
2272 if (!strcmp(args[cur_arg], "query-string")) {
2273 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2274 curproxy->options2 |= PR_O2_AS_M_QS;
2275 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2276 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2277 curproxy->options2 |= PR_O2_AS_M_PP;
2278 } else {
2279 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002284 cur_arg++;
2285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 } /* Url App Session */
2287 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002288 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002292 if (curproxy == &defproxy) {
2293 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2294 err_code |= ERR_ALERT | ERR_FATAL;
2295 goto out;
2296 }
2297
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 if (*(args[4]) == 0) {
2299 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2300 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002304 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 curproxy->capture_name = strdup(args[2]);
2306 curproxy->capture_namelen = strlen(curproxy->capture_name);
2307 curproxy->capture_len = atol(args[4]);
2308 if (curproxy->capture_len >= CAPTURE_LEN) {
2309 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2310 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 curproxy->capture_len = CAPTURE_LEN - 1;
2313 }
2314 curproxy->to_log |= LW_COOKIE;
2315 }
2316 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2317 struct cap_hdr *hdr;
2318
2319 if (curproxy == &defproxy) {
2320 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 +02002321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 }
2324
2325 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2326 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2327 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 }
2331
2332 hdr = calloc(sizeof(struct cap_hdr), 1);
2333 hdr->next = curproxy->req_cap;
2334 hdr->name = strdup(args[3]);
2335 hdr->namelen = strlen(args[3]);
2336 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002337 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 hdr->index = curproxy->nb_req_cap++;
2339 curproxy->req_cap = hdr;
2340 curproxy->to_log |= LW_REQHDR;
2341 }
2342 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2343 struct cap_hdr *hdr;
2344
2345 if (curproxy == &defproxy) {
2346 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 +02002347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 }
2350
2351 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2352 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2353 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 hdr = calloc(sizeof(struct cap_hdr), 1);
2358 hdr->next = curproxy->rsp_cap;
2359 hdr->name = strdup(args[3]);
2360 hdr->namelen = strlen(args[3]);
2361 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002362 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 hdr->index = curproxy->nb_rsp_cap++;
2364 curproxy->rsp_cap = hdr;
2365 curproxy->to_log |= LW_RSPHDR;
2366 }
2367 else {
2368 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002377
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 if (*(args[1]) == 0) {
2379 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2380 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 }
2384 curproxy->conn_retries = atol(args[1]);
2385 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002386 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002387 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002388
2389 if (curproxy == &defproxy) {
2390 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
2393 }
2394
Willy Tarreauff011f22011-01-06 17:51:27 +01002395 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 +01002396 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2397 file, linenum, args[0]);
2398 err_code |= ERR_WARN;
2399 }
2400
Willy Tarreauff011f22011-01-06 17:51:27 +01002401 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002402
Willy Tarreauff011f22011-01-06 17:51:27 +01002403 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002404 err_code |= ERR_ALERT | ERR_ABORT;
2405 goto out;
2406 }
2407
Willy Tarreauff011f22011-01-06 17:51:27 +01002408 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2409 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002410 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002411 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2412 /* set the header name and length into the proxy structure */
2413 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2414 err_code |= ERR_WARN;
2415
2416 if (!*args[1]) {
2417 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2418 file, linenum, args[0]);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
2422
2423 /* set the desired header name */
2424 free(curproxy->server_id_hdr_name);
2425 curproxy->server_id_hdr_name = strdup(args[1]);
2426 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2427 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002428 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002429 if (curproxy == &defproxy) {
2430 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002433 }
2434
Willy Tarreauef6494c2010-01-28 17:12:36 +01002435 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002436 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002440 }
2441
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002442 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2443 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2444 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002447 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002448
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002449 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002450 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002451 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002452 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002453 struct redirect_rule *rule;
2454 int cur_arg;
2455 int type = REDIRECT_TYPE_NONE;
2456 int code = 302;
2457 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002458 char *cookie = NULL;
2459 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002460 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002461
Cyril Bonté99ed3272010-01-24 23:29:44 +01002462 if (curproxy == &defproxy) {
2463 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
2466 }
2467
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002468 cur_arg = 1;
2469 while (*(args[cur_arg])) {
2470 if (!strcmp(args[cur_arg], "location")) {
2471 if (!*args[cur_arg + 1]) {
2472 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2473 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002476 }
2477
2478 type = REDIRECT_TYPE_LOCATION;
2479 cur_arg++;
2480 destination = args[cur_arg];
2481 }
2482 else if (!strcmp(args[cur_arg], "prefix")) {
2483 if (!*args[cur_arg + 1]) {
2484 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2485 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002488 }
2489
2490 type = REDIRECT_TYPE_PREFIX;
2491 cur_arg++;
2492 destination = args[cur_arg];
2493 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002494 else if (!strcmp(args[cur_arg], "scheme")) {
2495 if (!*args[cur_arg + 1]) {
2496 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2497 file, linenum, args[0], args[cur_arg]);
2498 err_code |= ERR_ALERT | ERR_FATAL;
2499 goto out;
2500 }
2501
2502 type = REDIRECT_TYPE_SCHEME;
2503 cur_arg++;
2504 destination = args[cur_arg];
2505 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002506 else if (!strcmp(args[cur_arg], "set-cookie")) {
2507 if (!*args[cur_arg + 1]) {
2508 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2509 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002512 }
2513
2514 cur_arg++;
2515 cookie = args[cur_arg];
2516 cookie_set = 1;
2517 }
2518 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2519 if (!*args[cur_arg + 1]) {
2520 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2521 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002522 err_code |= ERR_ALERT | ERR_FATAL;
2523 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002524 }
2525
2526 cur_arg++;
2527 cookie = args[cur_arg];
2528 cookie_set = 0;
2529 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 else if (!strcmp(args[cur_arg],"code")) {
2531 if (!*args[cur_arg + 1]) {
2532 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002536 }
2537 cur_arg++;
2538 code = atol(args[cur_arg]);
2539 if (code < 301 || code > 303) {
2540 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2541 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002544 }
2545 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002546 else if (!strcmp(args[cur_arg],"drop-query")) {
2547 flags |= REDIRECT_FLAG_DROP_QS;
2548 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002549 else if (!strcmp(args[cur_arg],"append-slash")) {
2550 flags |= REDIRECT_FLAG_APPEND_SLASH;
2551 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002552 else if (strcmp(args[cur_arg], "if") == 0 ||
2553 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002554 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002555 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002556 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2557 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
2560 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002561 break;
2562 }
2563 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002564 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 +02002565 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002568 }
2569 cur_arg++;
2570 }
2571
2572 if (type == REDIRECT_TYPE_NONE) {
2573 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\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
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2580 rule->cond = cond;
2581 rule->rdr_str = strdup(destination);
2582 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002583 if (cookie) {
2584 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002585 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002586 */
2587 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002588 if (cookie_set) {
2589 rule->cookie_str = malloc(rule->cookie_len + 10);
2590 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2591 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2592 rule->cookie_len += 9;
2593 } else {
2594 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002595 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002596 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2597 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002598 }
2599 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 rule->type = type;
2601 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002602 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002603 LIST_INIT(&rule->list);
2604 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002605 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2606 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002607 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002608 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002609 struct switching_rule *rule;
2610
Willy Tarreaub099aca2008-10-12 17:26:37 +02002611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002615 }
2616
Willy Tarreau55ea7572007-06-17 19:56:27 +02002617 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002619
2620 if (*(args[1]) == 0) {
2621 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002624 }
2625
Willy Tarreauef6494c2010-01-28 17:12:36 +01002626 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002631 }
2632
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002633 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2634 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2635 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638 }
2639
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002640 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002641
Willy Tarreau55ea7572007-06-17 19:56:27 +02002642 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2643 rule->cond = cond;
2644 rule->be.name = strdup(args[1]);
2645 LIST_INIT(&rule->list);
2646 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2647 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002648 else if (strcmp(args[0], "use-server") == 0) {
2649 struct server_rule *rule;
2650
2651 if (curproxy == &defproxy) {
2652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656
2657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2658 err_code |= ERR_WARN;
2659
2660 if (*(args[1]) == 0) {
2661 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
2666 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2667 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2668 file, linenum, args[0]);
2669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
2671 }
2672
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002673 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2674 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2675 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
2678 }
2679
2680 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2681
2682 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2683 rule->cond = cond;
2684 rule->srv.name = strdup(args[1]);
2685 LIST_INIT(&rule->list);
2686 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2687 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2688 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 else if ((!strcmp(args[0], "force-persist")) ||
2690 (!strcmp(args[0], "ignore-persist"))) {
2691 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002692
2693 if (curproxy == &defproxy) {
2694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
2697 }
2698
2699 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2700 err_code |= ERR_WARN;
2701
Willy Tarreauef6494c2010-01-28 17:12:36 +01002702 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2704 file, linenum, args[0]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
2708
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002709 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2710 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2711 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002716 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002717
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002718 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002719 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002720 if (!strcmp(args[0], "force-persist")) {
2721 rule->type = PERSIST_TYPE_FORCE;
2722 } else {
2723 rule->type = PERSIST_TYPE_IGNORE;
2724 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002725 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002727 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 else if (!strcmp(args[0], "stick-table")) {
2729 int myidx = 1;
2730
Emeric Brun32da3c42010-09-23 18:39:19 +02002731 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 curproxy->table.type = (unsigned int)-1;
2733 while (*args[myidx]) {
2734 const char *err;
2735
2736 if (strcmp(args[myidx], "size") == 0) {
2737 myidx++;
2738 if (!*(args[myidx])) {
2739 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2740 file, linenum, args[myidx-1]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2745 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2746 file, linenum, *err, args[myidx-1]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002750 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002751 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002752 else if (strcmp(args[myidx], "peers") == 0) {
2753 myidx++;
2754 if (!*(args[myidx])) {
2755 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2756 file, linenum, args[myidx-1]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760 curproxy->table.peers.name = strdup(args[myidx++]);
2761 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002762 else if (strcmp(args[myidx], "expire") == 0) {
2763 myidx++;
2764 if (!*(args[myidx])) {
2765 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2766 file, linenum, args[myidx-1]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2771 if (err) {
2772 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2773 file, linenum, *err, args[myidx-1]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002778 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002779 }
2780 else if (strcmp(args[myidx], "nopurge") == 0) {
2781 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002782 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002783 }
2784 else if (strcmp(args[myidx], "type") == 0) {
2785 myidx++;
2786 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2787 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2788 file, linenum, args[myidx]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002792 /* myidx already points to next arg */
2793 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002794 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002795 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002796 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002797
2798 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 nw = args[myidx];
2800 while (*nw) {
2801 /* the "store" keyword supports a comma-separated list */
2802 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002803 sa = NULL; /* store arg */
2804 while (*nw && *nw != ',') {
2805 if (*nw == '(') {
2806 *nw = 0;
2807 sa = ++nw;
2808 while (*nw != ')') {
2809 if (!*nw) {
2810 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2811 file, linenum, args[0], cw);
2812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815 nw++;
2816 }
2817 *nw = '\0';
2818 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002819 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002820 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002821 if (*nw)
2822 *nw++ = '\0';
2823 type = stktable_get_data_type(cw);
2824 if (type < 0) {
2825 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
Willy Tarreauac782882010-06-20 10:41:54 +02002830
2831 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2832 switch (err) {
2833 case PE_NONE: break;
2834 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2836 file, linenum, args[0], cw);
2837 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002838 break;
2839
2840 case PE_ARG_MISSING:
2841 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2842 file, linenum, args[0], cw);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845
2846 case PE_ARG_NOT_USED:
2847 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2848 file, linenum, args[0], cw);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851
2852 default:
2853 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2854 file, linenum, args[0], cw);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002857 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002858 }
2859 myidx++;
2860 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002861 else {
2862 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2863 file, linenum, args[myidx]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002867 }
2868
2869 if (!curproxy->table.size) {
2870 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2871 file, linenum);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875
2876 if (curproxy->table.type == (unsigned int)-1) {
2877 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2878 file, linenum);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
2883 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002884 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002885 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002886 int myidx = 0;
2887 const char *name = NULL;
2888 int flags;
2889
2890 if (curproxy == &defproxy) {
2891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2897 err_code |= ERR_WARN;
2898 goto out;
2899 }
2900
2901 myidx++;
2902 if ((strcmp(args[myidx], "store") == 0) ||
2903 (strcmp(args[myidx], "store-request") == 0)) {
2904 myidx++;
2905 flags = STK_IS_STORE;
2906 }
2907 else if (strcmp(args[myidx], "store-response") == 0) {
2908 myidx++;
2909 flags = STK_IS_STORE | STK_ON_RSP;
2910 }
2911 else if (strcmp(args[myidx], "match") == 0) {
2912 myidx++;
2913 flags = STK_IS_MATCH;
2914 }
2915 else if (strcmp(args[myidx], "on") == 0) {
2916 myidx++;
2917 flags = STK_IS_MATCH | STK_IS_STORE;
2918 }
2919 else {
2920 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924
2925 if (*(args[myidx]) == 0) {
2926 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
Willy Tarreauc919dc62012-10-26 17:35:22 +02002931 expr = sample_parse_expr(args, &myidx, trash, global.tune.bufsize);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002932 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002933 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937
2938 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002939 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002940 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2941 file, linenum, args[0], expr->fetch->kw);
2942 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002943 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 goto out;
2945 }
2946 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002947 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002948 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2949 file, linenum, args[0], expr->fetch->kw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002951 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002952 goto out;
2953 }
2954 }
2955
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02002956 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
2957 if (expr->fetch->cap & SMP_CAP_L7)
2958 curproxy->acl_requires |= ACL_USE_L7_ANY;
2959
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 if (strcmp(args[myidx], "table") == 0) {
2961 myidx++;
2962 name = args[myidx++];
2963 }
2964
Willy Tarreauef6494c2010-01-28 17:12:36 +01002965 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002966 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
2967 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
2968 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002969 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002970 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 goto out;
2972 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002973 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002974 else if (*(args[myidx])) {
2975 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2976 file, linenum, args[0], args[myidx]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002978 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002979 goto out;
2980 }
Emeric Brun97679e72010-09-23 17:56:44 +02002981 if (flags & STK_ON_RSP)
2982 err_code |= warnif_cond_requires_req(cond, file, linenum);
2983 else
2984 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002985
Emeric Brunb982a3d2010-01-04 15:45:53 +01002986 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2987 rule->cond = cond;
2988 rule->expr = expr;
2989 rule->flags = flags;
2990 rule->table.name = name ? strdup(name) : NULL;
2991 LIST_INIT(&rule->list);
2992 if (flags & STK_ON_RSP)
2993 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2994 else
2995 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002999 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3002 curproxy->uri_auth = NULL; /* we must detach from the default config */
3003
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003004 if (!*args[1]) {
3005 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003006 } else if (!strcmp(args[1], "admin")) {
3007 struct stats_admin_rule *rule;
3008
3009 if (curproxy == &defproxy) {
3010 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013 }
3014
3015 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3016 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3017 err_code |= ERR_ALERT | ERR_ABORT;
3018 goto out;
3019 }
3020
3021 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3022 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3023 file, linenum, args[0], args[1]);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003027 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3028 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3029 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
3033
3034 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3035
3036 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3037 rule->cond = cond;
3038 LIST_INIT(&rule->list);
3039 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 } else if (!strcmp(args[1], "uri")) {
3041 if (*(args[2]) == 0) {
3042 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3046 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003047 err_code |= ERR_ALERT | ERR_ABORT;
3048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 }
3050 } else if (!strcmp(args[1], "realm")) {
3051 if (*(args[2]) == 0) {
3052 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003057 err_code |= ERR_ALERT | ERR_ABORT;
3058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003060 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003061 unsigned interval;
3062
3063 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3064 if (err) {
3065 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3066 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_FATAL;
3068 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003069 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3070 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003071 err_code |= ERR_ALERT | ERR_ABORT;
3072 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003073 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003074 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003075 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003076
3077 if (curproxy == &defproxy) {
3078 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
3083 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3084 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
3087 }
3088
Willy Tarreauff011f22011-01-06 17:51:27 +01003089 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3090 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003091 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3092 file, linenum, args[0]);
3093 err_code |= ERR_WARN;
3094 }
3095
Willy Tarreauff011f22011-01-06 17:51:27 +01003096 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003097
Willy Tarreauff011f22011-01-06 17:51:27 +01003098 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
3101 }
3102
Willy Tarreauff011f22011-01-06 17:51:27 +01003103 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3104 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003105
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 } else if (!strcmp(args[1], "auth")) {
3107 if (*(args[2]) == 0) {
3108 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003111 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 }
3116 } else if (!strcmp(args[1], "scope")) {
3117 if (*(args[2]) == 0) {
3118 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3122 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_ABORT;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
3126 } else if (!strcmp(args[1], "enable")) {
3127 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_ABORT;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003132 } else if (!strcmp(args[1], "hide-version")) {
3133 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_ALERT | ERR_ABORT;
3136 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003137 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003138 } else if (!strcmp(args[1], "show-legends")) {
3139 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3140 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
3143 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003144 } else if (!strcmp(args[1], "show-node")) {
3145
3146 if (*args[2]) {
3147 int i;
3148 char c;
3149
3150 for (i=0; args[2][i]; i++) {
3151 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003152 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3153 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003154 break;
3155 }
3156
3157 if (!i || args[2][i]) {
3158 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3159 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3160 file, linenum, args[0], args[1]);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164 }
3165
3166 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3167 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3168 err_code |= ERR_ALERT | ERR_ABORT;
3169 goto out;
3170 }
3171 } else if (!strcmp(args[1], "show-desc")) {
3172 char *desc = NULL;
3173
3174 if (*args[2]) {
3175 int i, len=0;
3176 char *d;
3177
3178 for(i=2; *args[i]; i++)
3179 len += strlen(args[i])+1;
3180
3181 desc = d = (char *)calloc(1, len);
3182
3183 d += sprintf(d, "%s", args[2]);
3184 for(i=3; *args[i]; i++)
3185 d += sprintf(d, " %s", args[i]);
3186 }
3187
3188 if (!*args[2] && !global.desc)
3189 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3190 file, linenum, args[1]);
3191 else {
3192 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3193 free(desc);
3194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
3197 }
3198 free(desc);
3199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003201stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003202 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 +01003203 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 }
3207 }
3208 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209 int optnum;
3210
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003211 if (*(args[1]) == '\0') {
3212 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003217
3218 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3219 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003220 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3221 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3222 file, linenum, cfg_opts[optnum].name);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
Willy Tarreau93893792009-07-23 13:19:11 +02003226 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3227 err_code |= ERR_WARN;
3228 goto out;
3229 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003230
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 curproxy->no_options &= ~cfg_opts[optnum].val;
3232 curproxy->options &= ~cfg_opts[optnum].val;
3233
3234 switch (kwm) {
3235 case KWM_STD:
3236 curproxy->options |= cfg_opts[optnum].val;
3237 break;
3238 case KWM_NO:
3239 curproxy->no_options |= cfg_opts[optnum].val;
3240 break;
3241 case KWM_DEF: /* already cleared */
3242 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003243 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003244
Willy Tarreau93893792009-07-23 13:19:11 +02003245 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003246 }
3247 }
3248
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003249 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3250 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003251 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3252 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3253 file, linenum, cfg_opts2[optnum].name);
3254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
3256 }
Willy Tarreau93893792009-07-23 13:19:11 +02003257 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3258 err_code |= ERR_WARN;
3259 goto out;
3260 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003261
Willy Tarreau3842f002009-06-14 11:39:52 +02003262 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3263 curproxy->options2 &= ~cfg_opts2[optnum].val;
3264
3265 switch (kwm) {
3266 case KWM_STD:
3267 curproxy->options2 |= cfg_opts2[optnum].val;
3268 break;
3269 case KWM_NO:
3270 curproxy->no_options2 |= cfg_opts2[optnum].val;
3271 break;
3272 case KWM_DEF: /* already cleared */
3273 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003274 }
Willy Tarreau93893792009-07-23 13:19:11 +02003275 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003276 }
3277 }
3278
Willy Tarreau3842f002009-06-14 11:39:52 +02003279 if (kwm != KWM_STD) {
3280 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003281 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_FATAL;
3283 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003284 }
3285
Emeric Brun3a058f32009-06-30 18:26:00 +02003286 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003287 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003289 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 if (*(args[2]) != '\0') {
3291 if (!strcmp(args[2], "clf")) {
3292 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003293 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003294 } else {
3295 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003298 }
3299 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003300 if (curproxy->logformat_string != default_http_log_format &&
3301 curproxy->logformat_string != default_tcp_log_format &&
3302 curproxy->logformat_string != clf_http_log_format)
3303 free(curproxy->logformat_string);
3304 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003305 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003306 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003308 if (curproxy->logformat_string != default_http_log_format &&
3309 curproxy->logformat_string != default_tcp_log_format &&
3310 curproxy->logformat_string != clf_http_log_format)
3311 free(curproxy->logformat_string);
3312 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 else if (!strcmp(args[1], "tcpka")) {
3315 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003316 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318
3319 if (curproxy->cap & PR_CAP_FE)
3320 curproxy->options |= PR_O_TCP_CLI_KA;
3321 if (curproxy->cap & PR_CAP_BE)
3322 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
3324 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003325 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_WARN;
3327
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003329 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003330 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003331 curproxy->options2 &= ~PR_O2_CHK_ANY;
3332 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 if (!*args[2]) { /* no argument */
3334 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3335 curproxy->check_len = strlen(DEF_CHECK_REQ);
3336 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003337 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 curproxy->check_req = (char *)malloc(reqlen);
3339 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003340 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003342 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 if (*args[4])
3344 reqlen += strlen(args[4]);
3345 else
3346 reqlen += strlen("HTTP/1.0");
3347
3348 curproxy->check_req = (char *)malloc(reqlen);
3349 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003350 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003352 }
3353 else if (!strcmp(args[1], "ssl-hello-chk")) {
3354 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003355 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003357
Willy Tarreaua534fea2008-08-03 12:19:50 +02003358 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003359 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003360 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003361 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003362 }
Willy Tarreau23677902007-05-08 23:50:35 +02003363 else if (!strcmp(args[1], "smtpchk")) {
3364 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003365 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003366 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003367 curproxy->options2 &= ~PR_O2_CHK_ANY;
3368 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003369
3370 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3371 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3372 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3373 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3374 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3375 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3376 curproxy->check_req = (char *)malloc(reqlen);
3377 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3378 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3379 } else {
3380 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3381 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3382 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3383 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3384 }
3385 }
3386 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003387 else if (!strcmp(args[1], "pgsql-check")) {
3388 /* use PostgreSQL request to check servers' health */
3389 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3390 err_code |= ERR_WARN;
3391
3392 free(curproxy->check_req);
3393 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003394 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003395 curproxy->options2 |= PR_O2_PGSQL_CHK;
3396
3397 if (*(args[2])) {
3398 int cur_arg = 2;
3399
3400 while (*(args[cur_arg])) {
3401 if (strcmp(args[cur_arg], "user") == 0) {
3402 char * packet;
3403 uint32_t packet_len;
3404 uint32_t pv;
3405
3406 /* suboption header - needs additional argument for it */
3407 if (*(args[cur_arg+1]) == 0) {
3408 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3409 file, linenum, args[0], args[1], args[cur_arg]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
3413
3414 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3415 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3416 pv = htonl(0x30000); /* protocol version 3.0 */
3417
3418 packet = (char*) calloc(1, packet_len);
3419
3420 memcpy(packet + 4, &pv, 4);
3421
3422 /* copy "user" */
3423 memcpy(packet + 8, "user", 4);
3424
3425 /* copy username */
3426 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3427
3428 free(curproxy->check_req);
3429 curproxy->check_req = packet;
3430 curproxy->check_len = packet_len;
3431
3432 packet_len = htonl(packet_len);
3433 memcpy(packet, &packet_len, 4);
3434 cur_arg += 2;
3435 } else {
3436 /* unknown suboption - catchall */
3437 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3438 file, linenum, args[0], args[1]);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
3441 }
3442 } /* end while loop */
3443 }
3444 }
3445
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003446 else if (!strcmp(args[1], "redis-check")) {
3447 /* use REDIS PING request to check servers' health */
3448 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3449 err_code |= ERR_WARN;
3450
3451 free(curproxy->check_req);
3452 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003453 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003454 curproxy->options2 |= PR_O2_REDIS_CHK;
3455
3456 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3457 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3458 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3459 }
3460
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003461 else if (!strcmp(args[1], "mysql-check")) {
3462 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003463 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3464 err_code |= ERR_WARN;
3465
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003466 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003467 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003468 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003469 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003470
3471 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3472 * const char mysql40_client_auth_pkt[] = {
3473 * "\x0e\x00\x00" // packet length
3474 * "\x01" // packet number
3475 * "\x00\x00" // client capabilities
3476 * "\x00\x00\x01" // max packet
3477 * "haproxy\x00" // username (null terminated string)
3478 * "\x00" // filler (always 0x00)
3479 * "\x01\x00\x00" // packet length
3480 * "\x00" // packet number
3481 * "\x01" // COM_QUIT command
3482 * };
3483 */
3484
3485 if (*(args[2])) {
3486 int cur_arg = 2;
3487
3488 while (*(args[cur_arg])) {
3489 if (strcmp(args[cur_arg], "user") == 0) {
3490 char *mysqluser;
3491 int packetlen, reqlen, userlen;
3492
3493 /* suboption header - needs additional argument for it */
3494 if (*(args[cur_arg+1]) == 0) {
3495 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3496 file, linenum, args[0], args[1], args[cur_arg]);
3497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
3499 }
3500 mysqluser = args[cur_arg + 1];
3501 userlen = strlen(mysqluser);
3502 packetlen = userlen + 7;
3503 reqlen = packetlen + 9;
3504
3505 free(curproxy->check_req);
3506 curproxy->check_req = (char *)calloc(1, reqlen);
3507 curproxy->check_len = reqlen;
3508
3509 snprintf(curproxy->check_req, 4, "%c%c%c",
3510 ((unsigned char) packetlen & 0xff),
3511 ((unsigned char) (packetlen >> 8) & 0xff),
3512 ((unsigned char) (packetlen >> 16) & 0xff));
3513
3514 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003515 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003516 curproxy->check_req[8] = 1;
3517 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3518 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3519 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3520 cur_arg += 2;
3521 } else {
3522 /* unknown suboption - catchall */
3523 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3524 file, linenum, args[0], args[1]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528 } /* end while loop */
3529 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003530 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003531 else if (!strcmp(args[1], "ldap-check")) {
3532 /* use LDAP request to check servers' health */
3533 free(curproxy->check_req);
3534 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003535 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003536 curproxy->options2 |= PR_O2_LDAP_CHK;
3537
3538 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3539 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3540 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3541 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003542 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 int cur_arg;
3544
3545 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3546 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003547 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003548
Willy Tarreau87cf5142011-08-19 22:57:24 +02003549 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003550
3551 free(curproxy->fwdfor_hdr_name);
3552 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3553 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3554
3555 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3556 cur_arg = 2;
3557 while (*(args[cur_arg])) {
3558 if (!strcmp(args[cur_arg], "except")) {
3559 /* suboption except - needs additional argument for it */
3560 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3561 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3562 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003565 }
3566 /* flush useless bits */
3567 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003568 cur_arg += 2;
3569 } else if (!strcmp(args[cur_arg], "header")) {
3570 /* suboption header - needs additional argument for it */
3571 if (*(args[cur_arg+1]) == 0) {
3572 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3573 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003576 }
3577 free(curproxy->fwdfor_hdr_name);
3578 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3579 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3580 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003581 } else if (!strcmp(args[cur_arg], "if-none")) {
3582 curproxy->options &= ~PR_O_FF_ALWAYS;
3583 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003584 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003585 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003590 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003591 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003592 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003593 else if (!strcmp(args[1], "originalto")) {
3594 int cur_arg;
3595
3596 /* insert x-original-to field, but not for the IP address listed as an except.
3597 * set default options (ie: bitfield, header name, etc)
3598 */
3599
3600 curproxy->options |= PR_O_ORGTO;
3601
3602 free(curproxy->orgto_hdr_name);
3603 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3604 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3605
Willy Tarreau87cf5142011-08-19 22:57:24 +02003606 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003607 cur_arg = 2;
3608 while (*(args[cur_arg])) {
3609 if (!strcmp(args[cur_arg], "except")) {
3610 /* suboption except - needs additional argument for it */
3611 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3612 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3613 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003616 }
3617 /* flush useless bits */
3618 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3619 cur_arg += 2;
3620 } else if (!strcmp(args[cur_arg], "header")) {
3621 /* suboption header - needs additional argument for it */
3622 if (*(args[cur_arg+1]) == 0) {
3623 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3624 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_FATAL;
3626 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003627 }
3628 free(curproxy->orgto_hdr_name);
3629 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3630 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3631 cur_arg += 2;
3632 } else {
3633 /* unknown suboption - catchall */
3634 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3635 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003638 }
3639 } /* end while loop */
3640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 else {
3642 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 }
Willy Tarreau93893792009-07-23 13:19:11 +02003646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003648 else if (!strcmp(args[0], "default_backend")) {
3649 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003650 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003651
3652 if (*(args[1]) == 0) {
3653 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003656 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003657 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003658 curproxy->defbe.name = strdup(args[1]);
3659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003660 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003661 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003663
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003664 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3665 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 /* enable reconnections to dispatch */
3668 curproxy->options |= PR_O_REDISP;
3669 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003670 else if (!strcmp(args[0], "http-check")) {
3671 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003673
3674 if (strcmp(args[1], "disable-on-404") == 0) {
3675 /* enable a graceful server shutdown on an HTTP 404 response */
3676 curproxy->options |= PR_O_DISABLE404;
3677 }
Willy Tarreauef781042010-01-27 11:53:01 +01003678 else if (strcmp(args[1], "send-state") == 0) {
3679 /* enable emission of the apparent state of a server in HTTP checks */
3680 curproxy->options2 |= PR_O2_CHK_SNDST;
3681 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003682 else if (strcmp(args[1], "expect") == 0) {
3683 const char *ptr_arg;
3684 int cur_arg;
3685
3686 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3687 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
3692 cur_arg = 2;
3693 /* consider exclamation marks, sole or at the beginning of a word */
3694 while (*(ptr_arg = args[cur_arg])) {
3695 while (*ptr_arg == '!') {
3696 curproxy->options2 ^= PR_O2_EXP_INV;
3697 ptr_arg++;
3698 }
3699 if (*ptr_arg)
3700 break;
3701 cur_arg++;
3702 }
3703 /* now ptr_arg points to the beginning of a word past any possible
3704 * exclamation mark, and cur_arg is the argument which holds this word.
3705 */
3706 if (strcmp(ptr_arg, "status") == 0) {
3707 if (!*(args[cur_arg + 1])) {
3708 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3709 file, linenum, args[0], args[1], ptr_arg);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
3713 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003714 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003715 curproxy->expect_str = strdup(args[cur_arg + 1]);
3716 }
3717 else if (strcmp(ptr_arg, "string") == 0) {
3718 if (!*(args[cur_arg + 1])) {
3719 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3720 file, linenum, args[0], args[1], ptr_arg);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003725 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003726 curproxy->expect_str = strdup(args[cur_arg + 1]);
3727 }
3728 else if (strcmp(ptr_arg, "rstatus") == 0) {
3729 if (!*(args[cur_arg + 1])) {
3730 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3731 file, linenum, args[0], args[1], ptr_arg);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003736 free(curproxy->expect_str);
3737 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3738 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003739 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3740 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3741 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3742 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
3745 }
3746 }
3747 else if (strcmp(ptr_arg, "rstring") == 0) {
3748 if (!*(args[cur_arg + 1])) {
3749 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> 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_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003755 free(curproxy->expect_str);
3756 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3757 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003758 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3759 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3760 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3761 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765 }
3766 else {
3767 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3768 file, linenum, args[0], args[1], ptr_arg);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003773 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003774 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 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003777 }
3778 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003779 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003780 if (curproxy == &defproxy) {
3781 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003784 }
3785
Willy Tarreaub80c2302007-11-30 20:51:32 +01003786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003788
3789 if (strcmp(args[1], "fail") == 0) {
3790 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003791 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003792 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3793 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003796 }
3797
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003798 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3799 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3800 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003803 }
3804 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3805 }
3806 else {
3807 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003810 }
3811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812#ifdef TPROXY
3813 else if (!strcmp(args[0], "transparent")) {
3814 /* enable transparent proxy connections */
3815 curproxy->options |= PR_O_TRANSP;
3816 }
3817#endif
3818 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003819 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003820 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003821
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 if (*(args[1]) == 0) {
3823 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 }
3827 curproxy->maxconn = atol(args[1]);
3828 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003829 else if (!strcmp(args[0], "backlog")) { /* backlog */
3830 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003832
3833 if (*(args[1]) == 0) {
3834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003837 }
3838 curproxy->backlog = atol(args[1]);
3839 }
Willy Tarreau86034312006-12-29 00:10:33 +01003840 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003841 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843
Willy Tarreau86034312006-12-29 00:10:33 +01003844 if (*(args[1]) == 0) {
3845 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003848 }
3849 curproxy->fullconn = atol(args[1]);
3850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3852 if (*(args[1]) == 0) {
3853 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003857 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3858 if (err) {
3859 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3860 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003863 }
3864 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 }
3866 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003867 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 if (curproxy == &defproxy) {
3869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003873 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003875
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 if (strchr(args[1], ':') == NULL) {
3877 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003881 sk = str2sa(args[1]);
3882 if (!sk) {
3883 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
3886 }
3887 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003888 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
3890 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003893
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003894 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3895 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003900 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3902 err_code |= ERR_WARN;
3903
3904 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3905 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3906 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3907 }
3908 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3909 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3910 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3911 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003912 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3913 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3914 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3915 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003916 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003917 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
3920 }
3921 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003924 char *rport, *raddr;
3925 short realport = 0;
3926 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003933 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935
3936 if (!*args[2]) {
3937 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003942
3943 err = invalid_char(args[1]);
3944 if (err) {
3945 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3946 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003949 }
3950
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003952 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003953
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003954 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3955 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3956 err_code |= ERR_ALERT | ERR_ABORT;
3957 goto out;
3958 }
3959
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960 /* the servers are linked backwards first */
3961 newsrv->next = curproxy->srv;
3962 curproxy->srv = newsrv;
3963 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02003964 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003966
Simon Hormanaf514952011-06-21 14:34:57 +09003967 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003968 LIST_INIT(&newsrv->pendconns);
3969 do_check = 0;
3970 newsrv->state = SRV_RUNNING; /* early server setup */
3971 newsrv->last_change = now.tv_sec;
3972 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003974 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003975 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003976 * - IP: => port=+0, relative
3977 * - IP:N => port=N, absolute
3978 * - IP:+N => port=+N, relative
3979 * - IP:-N => port=-N, relative
3980 */
3981 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003982 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003983 if (rport) {
3984 *rport++ = 0;
3985 realport = atol(rport);
3986 if (!isdigit((unsigned char)*rport))
3987 newsrv->state |= SRV_MAPPORTS;
3988 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003990
Willy Tarreaufab5a432011-03-04 15:31:53 +01003991 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003993 if (!sk) {
3994 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02003999 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4000 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004001
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004002 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004003 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4004 file, linenum, newsrv->addr.ss_family, args[2]);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004008 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004009
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004010 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004011 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 newsrv->inter = curproxy->defsrv.inter;
4013 newsrv->fastinter = curproxy->defsrv.fastinter;
4014 newsrv->downinter = curproxy->defsrv.downinter;
4015 newsrv->rise = curproxy->defsrv.rise;
4016 newsrv->fall = curproxy->defsrv.fall;
4017 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4018 newsrv->minconn = curproxy->defsrv.minconn;
4019 newsrv->maxconn = curproxy->defsrv.maxconn;
4020 newsrv->slowstart = curproxy->defsrv.slowstart;
4021 newsrv->onerror = curproxy->defsrv.onerror;
4022 newsrv->consecutive_errors_limit
4023 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004024#ifdef OPENSSL
4025 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4026#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 newsrv->uweight = newsrv->iweight
4028 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004032 cur_arg = 3;
4033 } else {
4034 newsrv = &curproxy->defsrv;
4035 cur_arg = 1;
4036 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004037
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004039 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 newsrv->cookie = strdup(args[cur_arg + 1]);
4041 newsrv->cklen = strlen(args[cur_arg + 1]);
4042 cur_arg += 2;
4043 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004044 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004045 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4046 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4047 cur_arg += 2;
4048 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004050 if (!*args[cur_arg + 1]) {
4051 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4052 file, linenum, args[cur_arg]);
4053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
4055 }
4056
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004058 if (newsrv->rise <= 0) {
4059 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4060 file, linenum, args[cur_arg]);
4061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
4063 }
4064
Willy Tarreau96839092010-03-29 10:02:24 +02004065 if (newsrv->health)
4066 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 cur_arg += 2;
4068 }
4069 else if (!strcmp(args[cur_arg], "fall")) {
4070 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004071
4072 if (!*args[cur_arg + 1]) {
4073 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4074 file, linenum, args[cur_arg]);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078
4079 if (newsrv->fall <= 0) {
4080 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4081 file, linenum, args[cur_arg]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 cur_arg += 2;
4087 }
4088 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004089 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4090 if (err) {
4091 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4092 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004095 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004096 if (val <= 0) {
4097 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4098 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004101 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004102 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103 cur_arg += 2;
4104 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004105 else if (!strcmp(args[cur_arg], "fastinter")) {
4106 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4107 if (err) {
4108 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4109 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004112 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004113 if (val <= 0) {
4114 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4115 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004118 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 newsrv->fastinter = val;
4120 cur_arg += 2;
4121 }
4122 else if (!strcmp(args[cur_arg], "downinter")) {
4123 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4124 if (err) {
4125 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4126 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004129 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004130 if (val <= 0) {
4131 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4132 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004135 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004136 newsrv->downinter = val;
4137 cur_arg += 2;
4138 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004139 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004140 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004141 if (!sk) {
4142 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
4145 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004146 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004147 cur_arg += 2;
4148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004150 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 cur_arg += 2;
4152 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 newsrv->state |= SRV_BACKUP;
4155 cur_arg ++;
4156 }
Simon Hormanfa461682011-06-25 09:39:49 +09004157 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4158 newsrv->state |= SRV_NON_STICK;
4159 cur_arg ++;
4160 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004161 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4162 newsrv->state |= SRV_SEND_PROXY;
4163 cur_arg ++;
4164 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004165 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4166 newsrv->check.send_proxy = 1;
4167 cur_arg ++;
4168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 else if (!strcmp(args[cur_arg], "weight")) {
4170 int w;
4171 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004172 if (w < 0 || w > 256) {
4173 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004177 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004178 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004179 cur_arg += 2;
4180 }
4181 else if (!strcmp(args[cur_arg], "minconn")) {
4182 newsrv->minconn = atol(args[cur_arg + 1]);
4183 cur_arg += 2;
4184 }
4185 else if (!strcmp(args[cur_arg], "maxconn")) {
4186 newsrv->maxconn = atol(args[cur_arg + 1]);
4187 cur_arg += 2;
4188 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004189 else if (!strcmp(args[cur_arg], "maxqueue")) {
4190 newsrv->maxqueue = atol(args[cur_arg + 1]);
4191 cur_arg += 2;
4192 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004193 else if (!strcmp(args[cur_arg], "slowstart")) {
4194 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004195 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004196 if (err) {
4197 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4198 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004201 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004202 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004203 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4204 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004207 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004208 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004209 cur_arg += 2;
4210 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004211 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004212
4213 if (!*args[cur_arg + 1]) {
4214 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4215 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004218 }
4219
4220 newsrv->trackit = strdup(args[cur_arg + 1]);
4221
4222 cur_arg += 2;
4223 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004224 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 global.maxsock++;
4226 do_check = 1;
4227 cur_arg += 1;
4228 }
Willy Tarreau96839092010-03-29 10:02:24 +02004229 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4230 newsrv->state |= SRV_MAINTAIN;
4231 newsrv->state &= ~SRV_RUNNING;
4232 newsrv->health = 0;
4233 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004234 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004235 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004236 if (!strcmp(args[cur_arg + 1], "none"))
4237 newsrv->observe = HANA_OBS_NONE;
4238 else if (!strcmp(args[cur_arg + 1], "layer4"))
4239 newsrv->observe = HANA_OBS_LAYER4;
4240 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4241 if (curproxy->mode != PR_MODE_HTTP) {
4242 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4243 file, linenum, args[cur_arg + 1]);
4244 err_code |= ERR_ALERT;
4245 }
4246 newsrv->observe = HANA_OBS_LAYER7;
4247 }
4248 else {
4249 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004250 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004251 file, linenum, args[cur_arg], args[cur_arg + 1]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 cur_arg += 2;
4257 }
4258 else if (!strcmp(args[cur_arg], "on-error")) {
4259 if (!strcmp(args[cur_arg + 1], "fastinter"))
4260 newsrv->onerror = HANA_ONERR_FASTINTER;
4261 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4262 newsrv->onerror = HANA_ONERR_FAILCHK;
4263 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4264 newsrv->onerror = HANA_ONERR_SUDDTH;
4265 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4266 newsrv->onerror = HANA_ONERR_MARKDWN;
4267 else {
4268 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004269 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004270 file, linenum, args[cur_arg], args[cur_arg + 1]);
4271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
4273 }
4274
4275 cur_arg += 2;
4276 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004277 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4278 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4279 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4280 else {
4281 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4282 file, linenum, args[cur_arg], args[cur_arg + 1]);
4283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
4285 }
4286
4287 cur_arg += 2;
4288 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004289 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4290 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4291 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4292 else {
4293 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4294 file, linenum, args[cur_arg], args[cur_arg + 1]);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298
4299 cur_arg += 2;
4300 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004301 else if (!strcmp(args[cur_arg], "error-limit")) {
4302 if (!*args[cur_arg + 1]) {
4303 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4304 file, linenum, args[cur_arg]);
4305 err_code |= ERR_ALERT | ERR_FATAL;
4306 goto out;
4307 }
4308
4309 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4310
4311 if (newsrv->consecutive_errors_limit <= 0) {
4312 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4313 file, linenum, args[cur_arg]);
4314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
4316 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004317 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004318 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004319 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004320 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004321 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004322
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004324#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004325 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004326 file, linenum, "source", "usesrc");
4327#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004328 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004330#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004333 }
4334 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004335 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4336 if (!sk) {
4337 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
4340 }
4341 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004342
4343 if (port_low != port_high) {
4344 int i;
4345 if (port_low <= 0 || port_low > 65535 ||
4346 port_high <= 0 || port_high > 65535 ||
4347 port_low > port_high) {
4348 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4349 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004352 }
4353 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4354 for (i = 0; i < newsrv->sport_range->size; i++)
4355 newsrv->sport_range->ports[i] = port_low + i;
4356 }
4357
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004359 while (*(args[cur_arg])) {
4360 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004361#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4362#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004363 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4364 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4365 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004368 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004369#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004370 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004371 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004375 }
4376 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004377 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004378 newsrv->state |= SRV_TPROXY_CLI;
4379 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004380 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004382 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4383 char *name, *end;
4384
4385 name = args[cur_arg+1] + 7;
4386 while (isspace(*name))
4387 name++;
4388
4389 end = name;
4390 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4391 end++;
4392
4393 newsrv->state &= ~SRV_TPROXY_MASK;
4394 newsrv->state |= SRV_TPROXY_DYN;
4395 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4396 newsrv->bind_hdr_len = end - name;
4397 memcpy(newsrv->bind_hdr_name, name, end - name);
4398 newsrv->bind_hdr_name[end-name] = '\0';
4399 newsrv->bind_hdr_occ = -1;
4400
4401 /* now look for an occurrence number */
4402 while (isspace(*end))
4403 end++;
4404 if (*end == ',') {
4405 end++;
4406 name = end;
4407 if (*end == '-')
4408 end++;
4409 while (isdigit(*end))
4410 end++;
4411 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4412 }
4413
4414 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4415 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4416 " occurrences values smaller than %d.\n",
4417 file, linenum, MAX_HDR_HISTORY);
4418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004421 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004422 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004423 if (!sk) {
4424 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
4427 }
4428 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 }
4431 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004432#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004433 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004434#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 cur_arg += 2;
4436 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004437#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004439 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4443 } /* "usesrc" */
4444
4445 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4446#ifdef SO_BINDTODEVICE
4447 if (!*args[cur_arg + 1]) {
4448 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004452 }
4453 if (newsrv->iface_name)
4454 free(newsrv->iface_name);
4455
4456 newsrv->iface_name = strdup(args[cur_arg + 1]);
4457 newsrv->iface_len = strlen(newsrv->iface_name);
4458 global.last_checks |= LSTCHK_NETADM;
4459#else
4460 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4461 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004464#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 cur_arg += 2;
4466 continue;
4467 }
4468 /* this keyword in not an option of "source" */
4469 break;
4470 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004472 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004473 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4474 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004479 static int srv_dumped;
4480 struct srv_kw *kw;
4481 char *err;
4482
4483 kw = srv_find_kw(args[cur_arg]);
4484 if (kw) {
4485 char *err = NULL;
4486 int code;
4487
4488 if (!kw->parse) {
4489 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4490 file, linenum, args[0], args[1], args[cur_arg]);
4491 cur_arg += 1 + kw->skip ;
4492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
4494 }
4495
4496 if (defsrv && !kw->default_ok) {
4497 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4498 file, linenum, args[0], args[1], args[cur_arg]);
4499 cur_arg += 1 + kw->skip ;
4500 err_code |= ERR_ALERT;
4501 continue;
4502 }
4503
4504 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4505 err_code |= code;
4506
4507 if (code) {
4508 if (err && *err) {
4509 indent_msg(&err, 2);
4510 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4511 }
4512 else
4513 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4514 file, linenum, args[0], args[1], args[cur_arg]);
4515 if (code & ERR_FATAL) {
4516 free(err);
4517 cur_arg += 1 + kw->skip;
4518 goto out;
4519 }
4520 }
4521 free(err);
4522 cur_arg += 1 + kw->skip;
4523 continue;
4524 }
4525
4526 err = NULL;
4527 if (!srv_dumped) {
4528 srv_dump_kws(&err);
4529 indent_msg(&err, 4);
4530 srv_dumped = 1;
4531 }
4532
4533 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4534 file, linenum, args[0], args[1], args[cur_arg],
4535 err ? " Registered keywords :" : "", err ? err : "");
4536 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004537
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 }
4541 }
4542
4543 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004544 if (newsrv->trackit) {
4545 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004549 }
4550
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004551 /* If neither a port nor an addr was specified and no check transport
4552 * layer is forced, then the transport layer used by the checks is the
4553 * same as for the production traffic. Otherwise we use raw_sock by
4554 * default, unless one is specified.
4555 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004556 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004557#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004558 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004559#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004560 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4561 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004562 /* try to get the port from check.addr if check.port not set */
4563 if (!newsrv->check.port)
4564 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004565
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004566 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4567 newsrv->check.port = realport; /* by default */
4568 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004569 /* not yet valid, because no port was set on
4570 * the server either. We'll check if we have
4571 * a known port on the first listener.
4572 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004573 struct listener *l;
4574
4575 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004576 newsrv->check.port = get_host_port(&l->addr);
4577 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004578 break;
4579 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004580 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004581 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4583 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004587
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004588 /* Allocate buffer for check requests... */
4589 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004590 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4591 err_code |= ERR_ALERT | ERR_ABORT;
4592 goto out;
4593 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004594 newsrv->check.bi->size = global.tune.chksize;
4595
4596 /* Allocate buffer for check responses... */
4597 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4598 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4599 err_code |= ERR_ALERT | ERR_ABORT;
4600 goto out;
4601 }
4602 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004603
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004604 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004605 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004606 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4607 err_code |= ERR_ALERT | ERR_ABORT;
4608 goto out;
4609 }
4610
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004611 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4612 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 newsrv->state |= SRV_CHECKED;
4614 }
4615
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004616 if (!defsrv) {
4617 if (newsrv->state & SRV_BACKUP)
4618 curproxy->srv_bck++;
4619 else
4620 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004621
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 newsrv->prev_state = newsrv->state;
4623 }
William Lallemanda73203e2012-03-12 12:48:57 +01004624 }
4625
4626 else if (strcmp(args[0], "unique-id-format") == 0) {
4627 if (!*(args[1])) {
4628 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004632 free(curproxy->uniqueid_format_string);
4633 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004634 }
William Lallemanda73203e2012-03-12 12:48:57 +01004635
4636 else if (strcmp(args[0], "unique-id-header") == 0) {
4637 if (!*(args[1])) {
4638 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 free(curproxy->header_unique_id);
4643 curproxy->header_unique_id = strdup(args[1]);
4644 }
4645
William Lallemand723b73a2012-02-08 16:37:49 +01004646 else if (strcmp(args[0], "log-format") == 0) {
4647 if (!*(args[1])) {
4648 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4649 err_code |= ERR_ALERT | ERR_FATAL;
4650 goto out;
4651 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004652
4653 if (curproxy->logformat_string != default_http_log_format &&
4654 curproxy->logformat_string != default_tcp_log_format &&
4655 curproxy->logformat_string != clf_http_log_format)
4656 free(curproxy->logformat_string);
4657 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004658 }
William Lallemand723b73a2012-02-08 16:37:49 +01004659
William Lallemand0f99e342011-10-12 17:50:54 +02004660 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4661 /* delete previous herited or defined syslog servers */
4662 struct logsrv *back;
4663
4664 if (*(args[1]) != 0) {
4665 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4666 err_code |= ERR_ALERT | ERR_FATAL;
4667 goto out;
4668 }
4669
William Lallemand723b73a2012-02-08 16:37:49 +01004670 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4671 LIST_DEL(&tmplogsrv->list);
4672 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004673 }
4674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004676 struct logsrv *logsrv;
4677
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004679 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004680 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004681 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004682 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004683 LIST_INIT(&node->list);
4684 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004686 }
4687 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004688
4689 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690
William Lallemand0f99e342011-10-12 17:50:54 +02004691 logsrv->facility = get_log_facility(args[2]);
4692 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
4696
Willy Tarreaubaaee002006-06-26 02:48:02 +02004697 }
4698
William Lallemand0f99e342011-10-12 17:50:54 +02004699 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004700 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004701 logsrv->level = get_log_level(args[3]);
4702 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
4706
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
4708 }
4709
William Lallemand0f99e342011-10-12 17:50:54 +02004710 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004711 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004712 logsrv->minlvl = get_log_level(args[4]);
4713 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004714 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004718 }
4719 }
4720
Robert Tsai81ae1952007-12-05 10:47:29 +01004721 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004722 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004723 if (!sk) {
4724 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004725 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
4728 }
William Lallemand0f99e342011-10-12 17:50:54 +02004729 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004730 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004731 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004732 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004733 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
4736 }
William Lallemand0f99e342011-10-12 17:50:54 +02004737 logsrv->addr = *sk;
4738 if (!get_host_port(&logsrv->addr))
4739 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
William Lallemand0f99e342011-10-12 17:50:54 +02004741
4742 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 else {
4745 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4746 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
4750 }
4751 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004752 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004753 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004754
Willy Tarreau977b8e42006-12-29 14:19:17 +01004755 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004756 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004757
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004759 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4760 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004764
4765 /* we must first clear any optional default setting */
4766 curproxy->options &= ~PR_O_TPXY_MASK;
4767 free(curproxy->iface_name);
4768 curproxy->iface_name = NULL;
4769 curproxy->iface_len = 0;
4770
Willy Tarreaud5191e72010-02-09 20:50:45 +01004771 sk = str2sa(args[1]);
4772 if (!sk) {
4773 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
4777 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004779
4780 cur_arg = 2;
4781 while (*(args[cur_arg])) {
4782 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004783#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4784#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004785 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4786 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4787 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004790 }
4791#endif
4792 if (!*args[cur_arg + 1]) {
4793 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4794 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004797 }
4798
4799 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004800 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 curproxy->options |= PR_O_TPXY_CLI;
4802 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004803 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004804 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004805 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4806 char *name, *end;
4807
4808 name = args[cur_arg+1] + 7;
4809 while (isspace(*name))
4810 name++;
4811
4812 end = name;
4813 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4814 end++;
4815
4816 curproxy->options &= ~PR_O_TPXY_MASK;
4817 curproxy->options |= PR_O_TPXY_DYN;
4818 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4819 curproxy->bind_hdr_len = end - name;
4820 memcpy(curproxy->bind_hdr_name, name, end - name);
4821 curproxy->bind_hdr_name[end-name] = '\0';
4822 curproxy->bind_hdr_occ = -1;
4823
4824 /* now look for an occurrence number */
4825 while (isspace(*end))
4826 end++;
4827 if (*end == ',') {
4828 end++;
4829 name = end;
4830 if (*end == '-')
4831 end++;
4832 while (isdigit(*end))
4833 end++;
4834 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4835 }
4836
4837 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4838 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4839 " occurrences values smaller than %d.\n",
4840 file, linenum, MAX_HDR_HISTORY);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004844 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004845 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004846 if (!sk) {
4847 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
4850 }
4851 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004852 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 }
4854 global.last_checks |= LSTCHK_NETADM;
4855#if !defined(CONFIG_HAP_LINUX_TPROXY)
4856 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004857#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004858#else /* no TPROXY support */
4859 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004860 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004863#endif
4864 cur_arg += 2;
4865 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004866 }
4867
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004868 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4869#ifdef SO_BINDTODEVICE
4870 if (!*args[cur_arg + 1]) {
4871 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4872 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 }
4876 if (curproxy->iface_name)
4877 free(curproxy->iface_name);
4878
4879 curproxy->iface_name = strdup(args[cur_arg + 1]);
4880 curproxy->iface_len = strlen(curproxy->iface_name);
4881 global.last_checks |= LSTCHK_NETADM;
4882#else
4883 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4884 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004887#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004888 cur_arg += 2;
4889 continue;
4890 }
4891 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004892 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004897 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4898 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4899 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004902 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910
4911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004912 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004913 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004919 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004926 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004927 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004933 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004940 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004945 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004947 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004951 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004952 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004954 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004958 }
4959 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4969 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973
4974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005003 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005004 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005008 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005016 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005017
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 if (curproxy == &defproxy) {
5019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005023 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 if (*(args[1]) == 0) {
5027 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005031
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005032 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005033 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5034 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5035 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
5038 }
5039 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5040 }
5041 else if (*args[2]) {
5042 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5043 file, linenum, args[0], args[2]);
5044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
5046 }
5047
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005048 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005049 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005050 wl->s = strdup(args[1]);
5051 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005052 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005055 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5057 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005061
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005063 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005064 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005065 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
5068 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005070 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005071 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 }
5075 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005077 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005078 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005079 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
5082 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 }
5089
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005091 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005092 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005093 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 }
5096 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005098 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005099 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005100 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005105 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005106 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005111 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005112
Willy Tarreaubaaee002006-06-26 02:48:02 +02005113 if (curproxy == &defproxy) {
5114 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005118 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 if (*(args[1]) == 0) {
5122 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005127 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005128 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5129 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5130 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
5133 }
5134 err_code |= warnif_cond_requires_req(cond, file, linenum);
5135 }
5136 else if (*args[2]) {
5137 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5138 file, linenum, args[0], args[2]);
5139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
5141 }
5142
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005143 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005144 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005145 wl->s = strdup(args[1]);
5146 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "errorloc") ||
5149 !strcmp(args[0], "errorloc302") ||
5150 !strcmp(args[0], "errorloc303")) { /* error location */
5151 int errnum, errlen;
5152 char *err;
5153
Willy Tarreau977b8e42006-12-29 14:19:17 +01005154 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005155 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005156
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005158 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162
5163 errnum = atol(args[1]);
5164 if (!strcmp(args[0], "errorloc303")) {
5165 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5166 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5167 } else {
5168 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5169 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5170 }
5171
Willy Tarreau0f772532006-12-23 20:51:41 +01005172 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5173 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005174 chunk_destroy(&curproxy->errmsg[rc]);
5175 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005176 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005178 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005179
5180 if (rc >= HTTP_ERR_SIZE) {
5181 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5182 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 free(err);
5184 }
5185 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005186 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5187 int errnum, errlen, fd;
5188 char *err;
5189 struct stat stat;
5190
5191 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005192 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005193
5194 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005195 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005198 }
5199
5200 fd = open(args[2], O_RDONLY);
5201 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5202 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5203 file, linenum, args[2], args[1]);
5204 if (fd >= 0)
5205 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005208 }
5209
Willy Tarreau27a674e2009-08-17 07:23:33 +02005210 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005211 errlen = stat.st_size;
5212 } else {
5213 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005214 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005216 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217 }
5218
5219 err = malloc(errlen); /* malloc() must succeed during parsing */
5220 errnum = read(fd, err, errlen);
5221 if (errnum != errlen) {
5222 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5223 file, linenum, args[2], args[1]);
5224 close(fd);
5225 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005228 }
5229 close(fd);
5230
5231 errnum = atol(args[1]);
5232 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5233 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005234 chunk_destroy(&curproxy->errmsg[rc]);
5235 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005236 break;
5237 }
5238 }
5239
5240 if (rc >= HTTP_ERR_SIZE) {
5241 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5242 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005243 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005244 free(err);
5245 }
5246 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005247 else if (!strcmp(args[0], "compression")) {
5248 struct comp *comp;
5249 if (curproxy->comp == NULL) {
5250 comp = calloc(1, sizeof(struct comp));
5251 curproxy->comp = comp;
5252 } else {
5253 comp = curproxy->comp;
5254 }
5255
5256 if (!strcmp(args[1], "algo")) {
5257 int cur_arg;
5258 cur_arg = 2;
5259 if (!*args[cur_arg]) {
5260 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5261 file, linenum, args[0]);
5262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265 while (*(args[cur_arg])) {
5266 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5267 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5268 file, linenum, args[0], args[cur_arg]);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 cur_arg ++;
5273 continue;
5274 }
5275 }
5276 else if (!strcmp(args[1], "type")) {
5277 int cur_arg;
5278 cur_arg = 2;
5279 if (!*args[cur_arg]) {
5280 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5281 file, linenum, args[0]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 while (*(args[cur_arg])) {
5286 comp_append_type(comp, args[cur_arg]);
5287 cur_arg ++;
5288 continue;
5289 }
5290 }
5291 else {
5292 Alert("parsing [%s:%d] : '%s' expects algo or type\n",
5293 file, linenum, args[0]);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005299 struct cfg_kw_list *kwl;
5300 int index;
5301
5302 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5303 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5304 if (kwl->kw[index].section != CFG_LISTEN)
5305 continue;
5306 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5307 /* prepare error message just in case */
Willy Tarreauc919dc62012-10-26 17:35:22 +02005308 snprintf(trash, global.tune.bufsize,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005309 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau28a47d62012-09-18 20:02:48 +02005310 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005311 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005312 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005315 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005316 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005317 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005318 err_code |= ERR_WARN;
5319 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005320 }
Willy Tarreau93893792009-07-23 13:19:11 +02005321 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005322 }
5323 }
5324 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005325
Willy Tarreau6daf3432008-01-22 16:44:08 +01005326 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
5328 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 }
Willy Tarreau93893792009-07-23 13:19:11 +02005330 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005331 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005332 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333}
5334
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005335int
5336cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5337{
5338
5339 int err_code = 0;
5340 const char *err;
5341
5342 if (!strcmp(args[0], "userlist")) { /* new userlist */
5343 struct userlist *newul;
5344
5345 if (!*args[1]) {
5346 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5347 file, linenum, args[0]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351
5352 err = invalid_char(args[1]);
5353 if (err) {
5354 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5355 file, linenum, *err, args[0], args[1]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359
5360 for (newul = userlist; newul; newul = newul->next)
5361 if (!strcmp(newul->name, args[1])) {
5362 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5363 file, linenum, args[1]);
5364 err_code |= ERR_WARN;
5365 goto out;
5366 }
5367
5368 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5369 if (!newul) {
5370 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5371 err_code |= ERR_ALERT | ERR_ABORT;
5372 goto out;
5373 }
5374
5375 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5376 newul->name = strdup(args[1]);
5377
5378 if (!newul->groupusers | !newul->name) {
5379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5380 err_code |= ERR_ALERT | ERR_ABORT;
5381 goto out;
5382 }
5383
5384 newul->next = userlist;
5385 userlist = newul;
5386
5387 } else if (!strcmp(args[0], "group")) { /* new group */
5388 int cur_arg, i;
5389 const char *err;
5390
5391 if (!*args[1]) {
5392 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5393 file, linenum, args[0]);
5394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
5396 }
5397
5398 err = invalid_char(args[1]);
5399 if (err) {
5400 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5401 file, linenum, *err, args[0], args[1]);
5402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
5405
5406 for(i = 0; i < userlist->grpcnt; i++)
5407 if (!strcmp(userlist->groups[i], args[1])) {
5408 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5409 file, linenum, args[1], userlist->name);
5410 err_code |= ERR_ALERT;
5411 goto out;
5412 }
5413
5414 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5415 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5416 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420
5421 cur_arg = 2;
5422
5423 while (*args[cur_arg]) {
5424 if (!strcmp(args[cur_arg], "users")) {
5425 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5426 cur_arg += 2;
5427 continue;
5428 } else {
5429 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5430 file, linenum, args[0]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
5434 }
5435
5436 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5437 } else if (!strcmp(args[0], "user")) { /* new user */
5438 struct auth_users *newuser;
5439 int cur_arg;
5440
5441 if (!*args[1]) {
5442 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5443 file, linenum, args[0]);
5444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447
5448 for (newuser = userlist->users; newuser; newuser = newuser->next)
5449 if (!strcmp(newuser->user, args[1])) {
5450 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5451 file, linenum, args[1], userlist->name);
5452 err_code |= ERR_ALERT;
5453 goto out;
5454 }
5455
5456 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5457 if (!newuser) {
5458 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5459 err_code |= ERR_ALERT | ERR_ABORT;
5460 goto out;
5461 }
5462
5463 newuser->user = strdup(args[1]);
5464
5465 newuser->next = userlist->users;
5466 userlist->users = newuser;
5467
5468 cur_arg = 2;
5469
5470 while (*args[cur_arg]) {
5471 if (!strcmp(args[cur_arg], "password")) {
5472#ifndef CONFIG_HAP_CRYPT
5473 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5474 file, linenum);
5475 err_code |= ERR_ALERT;
5476#endif
5477 newuser->pass = strdup(args[cur_arg + 1]);
5478 cur_arg += 2;
5479 continue;
5480 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5481 newuser->pass = strdup(args[cur_arg + 1]);
5482 newuser->flags |= AU_O_INSECURE;
5483 cur_arg += 2;
5484 continue;
5485 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005486 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005487 cur_arg += 2;
5488 continue;
5489 } else {
5490 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5491 file, linenum, args[0]);
5492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
5494 }
5495 }
5496 } else {
5497 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 }
5500
5501out:
5502 return err_code;
5503}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504
5505/*
5506 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005507 * Returns the error code, 0 if OK, or any combination of :
5508 * - ERR_ABORT: must abort ASAP
5509 * - ERR_FATAL: we can continue parsing but not start the service
5510 * - ERR_WARN: a warning has been emitted
5511 * - ERR_ALERT: an alert has been emitted
5512 * Only the two first ones can stop processing, the two others are just
5513 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005515int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005517 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 FILE *f;
5519 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005521 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 if ((f=fopen(file,"r")) == NULL)
5524 return -1;
5525
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005526 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005527 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005528 char *end;
5529 char *args[MAX_LINE_ARGS + 1];
5530 char *line = thisline;
5531
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 linenum++;
5533
5534 end = line + strlen(line);
5535
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005536 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5537 /* Check if we reached the limit and the last char is not \n.
5538 * Watch out for the last line without the terminating '\n'!
5539 */
5540 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005541 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005542 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005543 }
5544
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005546 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547 line++;
5548
5549 arg = 0;
5550 args[arg] = line;
5551
5552 while (*line && arg < MAX_LINE_ARGS) {
5553 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5554 * C equivalent value. Other combinations left unchanged (eg: \1).
5555 */
5556 if (*line == '\\') {
5557 int skip = 0;
5558 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5559 *line = line[1];
5560 skip = 1;
5561 }
5562 else if (line[1] == 'r') {
5563 *line = '\r';
5564 skip = 1;
5565 }
5566 else if (line[1] == 'n') {
5567 *line = '\n';
5568 skip = 1;
5569 }
5570 else if (line[1] == 't') {
5571 *line = '\t';
5572 skip = 1;
5573 }
5574 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005575 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 unsigned char hex1, hex2;
5577 hex1 = toupper(line[2]) - '0';
5578 hex2 = toupper(line[3]) - '0';
5579 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5580 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5581 *line = (hex1<<4) + hex2;
5582 skip = 3;
5583 }
5584 else {
5585 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 }
5588 }
5589 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005590 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 end -= skip;
5592 }
5593 line++;
5594 }
5595 else if (*line == '#' || *line == '\n' || *line == '\r') {
5596 /* end of string, end of loop */
5597 *line = 0;
5598 break;
5599 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005600 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005602 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005603 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 line++;
5605 args[++arg] = line;
5606 }
5607 else {
5608 line++;
5609 }
5610 }
5611
5612 /* empty line */
5613 if (!**args)
5614 continue;
5615
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005616 if (*line) {
5617 /* we had to stop due to too many args.
5618 * Let's terminate the string, print the offending part then cut the
5619 * last arg.
5620 */
5621 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5622 line++;
5623 *line = '\0';
5624
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005625 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005626 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 args[arg] = line;
5629 }
5630
Willy Tarreau540abe42007-05-02 20:50:16 +02005631 /* zero out remaining args and ensure that at least one entry
5632 * is zeroed out.
5633 */
5634 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 args[arg] = line;
5636 }
5637
Willy Tarreau3842f002009-06-14 11:39:52 +02005638 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005639 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005640 char *tmp;
5641
Willy Tarreau3842f002009-06-14 11:39:52 +02005642 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005643 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005644 for (arg=0; *args[arg+1]; arg++)
5645 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005646 *tmp = '\0'; // fix the next arg to \0
5647 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005648 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005649 else if (!strcmp(args[0], "default")) {
5650 kwm = KWM_DEF;
5651 for (arg=0; *args[arg+1]; arg++)
5652 args[arg] = args[arg+1]; // shift args after inversion
5653 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005654
William Lallemand0f99e342011-10-12 17:50:54 +02005655 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5656 strcmp(args[0], "log") != 0) {
5657 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005658 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005659 }
5660
Willy Tarreau977b8e42006-12-29 14:19:17 +01005661 if (!strcmp(args[0], "listen") ||
5662 !strcmp(args[0], "frontend") ||
5663 !strcmp(args[0], "backend") ||
5664 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005665 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005667 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005668 cursection = strdup(args[0]);
5669 }
5670 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005672 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005673 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005674 }
5675 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005676 confsect = CFG_USERLIST;
5677 free(cursection);
5678 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005679 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005680 else if (!strcmp(args[0], "peers")) {
5681 confsect = CFG_PEERS;
5682 free(cursection);
5683 cursection = strdup(args[0]);
5684 }
5685
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 /* else it's a section keyword */
5687
5688 switch (confsect) {
5689 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 break;
5692 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005693 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005695 case CFG_USERLIST:
5696 err_code |= cfg_parse_users(file, linenum, args, kwm);
5697 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005698 case CFG_PEERS:
5699 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5700 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005702 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005705
5706 if (err_code & ERR_ABORT)
5707 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005708 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005709 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005710 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005711 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005712 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005713}
5714
Willy Tarreaubb925012009-07-23 13:36:36 +02005715/*
5716 * Returns the error code, 0 if OK, or any combination of :
5717 * - ERR_ABORT: must abort ASAP
5718 * - ERR_FATAL: we can continue parsing but not start the service
5719 * - ERR_WARN: a warning has been emitted
5720 * - ERR_ALERT: an alert has been emitted
5721 * Only the two first ones can stop processing, the two others are just
5722 * indicators.
5723 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005724int check_config_validity()
5725{
5726 int cfgerr = 0;
5727 struct proxy *curproxy = NULL;
5728 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005729 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005730 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005731 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005732 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005734 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 /*
5736 * Now, check for the integrity of all that we have collected.
5737 */
5738
5739 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005740 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005742 /* first, we will invert the proxy list order */
5743 curproxy = NULL;
5744 while (proxy) {
5745 struct proxy *next;
5746
5747 next = proxy->next;
5748 proxy->next = curproxy;
5749 curproxy = proxy;
5750 if (!next)
5751 break;
5752 proxy = next;
5753 }
5754
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005756 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005757 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005758 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005759 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005760 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005761 unsigned int next_id;
5762
Willy Tarreau050536d2012-10-04 08:47:34 +02005763 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005764 /* proxy ID not set, use automatic numbering with first
5765 * spare entry starting with next_pxid.
5766 */
5767 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5768 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5769 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005770 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005771 next_pxid++;
5772
Willy Tarreau55ea7572007-06-17 19:56:27 +02005773
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005775 /* ensure we don't keep listeners uselessly bound */
5776 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 curproxy = curproxy->next;
5778 continue;
5779 }
5780
Willy Tarreauff01a212009-03-15 13:46:16 +01005781 switch (curproxy->mode) {
5782 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005783 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005784 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005785 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5786 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005787 cfgerr++;
5788 }
5789
5790 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005791 Warning("config : servers will be ignored for %s '%s'.\n",
5792 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005793 break;
5794
5795 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005796 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005797 break;
5798
5799 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005800 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005801 break;
5802 }
5803
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005804 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005805 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005806 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005807 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5808 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005809 cfgerr++;
5810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005812 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005813 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5814 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005815 cfgerr++;
5816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005818 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005819 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5820 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005821 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005822 }
5823 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005824 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005825 /* If no LB algo is set in a backend, and we're not in
5826 * transparent mode, dispatch mode nor proxy mode, we
5827 * want to use balance roundrobin by default.
5828 */
5829 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5830 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 }
5832 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005833
Willy Tarreau1620ec32011-08-06 17:05:02 +02005834 if (curproxy->options & PR_O_DISPATCH)
5835 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5836 else if (curproxy->options & PR_O_HTTP_PROXY)
5837 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5838 else if (curproxy->options & PR_O_TRANSP)
5839 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005840
Willy Tarreau1620ec32011-08-06 17:05:02 +02005841 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5842 if (curproxy->options & PR_O_DISABLE404) {
5843 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5844 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5845 err_code |= ERR_WARN;
5846 curproxy->options &= ~PR_O_DISABLE404;
5847 }
5848 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5849 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5850 "send-state", proxy_type_str(curproxy), curproxy->id);
5851 err_code |= ERR_WARN;
5852 curproxy->options &= ~PR_O2_CHK_SNDST;
5853 }
Willy Tarreauef781042010-01-27 11:53:01 +01005854 }
5855
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005856 /* if a default backend was specified, let's find it */
5857 if (curproxy->defbe.name) {
5858 struct proxy *target;
5859
Alex Williams96532db2009-11-01 21:27:13 -05005860 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005861 if (!target) {
5862 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5863 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005864 cfgerr++;
5865 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005866 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5867 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005868 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005869 } else {
5870 free(curproxy->defbe.name);
5871 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005872 /* we force the backend to be present on at least all of
5873 * the frontend's processes.
5874 */
5875 target->bind_proc = curproxy->bind_proc ?
5876 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005877
5878 /* Emit a warning if this proxy also has some servers */
5879 if (curproxy->srv) {
5880 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5881 curproxy->id);
5882 err_code |= ERR_WARN;
5883 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
5885 }
5886
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005887 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005888 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5889 /* map jump target for ACT_SETBE in req_rep chain */
5890 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005891 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005892 struct proxy *target;
5893
Willy Tarreaua496b602006-12-17 23:15:24 +01005894 if (exp->action != ACT_SETBE)
5895 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005896
Alex Williams96532db2009-11-01 21:27:13 -05005897 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005898 if (!target) {
5899 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5900 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005901 cfgerr++;
5902 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005903 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5904 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005905 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005906 } else {
5907 free((void *)exp->replace);
5908 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005909 /* we force the backend to be present on at least all of
5910 * the frontend's processes.
5911 */
5912 target->bind_proc = curproxy->bind_proc ?
5913 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005914 }
5915 }
5916 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005917
5918 /* find the target proxy for 'use_backend' rules */
5919 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005920 struct proxy *target;
5921
Alex Williams96532db2009-11-01 21:27:13 -05005922 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005923
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005924 if (!target) {
5925 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5926 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005927 cfgerr++;
5928 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005929 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5930 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005931 cfgerr++;
5932 } else {
5933 free((void *)rule->be.name);
5934 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005935 /* we force the backend to be present on at least all of
5936 * the frontend's processes.
5937 */
5938 target->bind_proc = curproxy->bind_proc ?
5939 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005940 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005941 }
5942
5943 /* find the target proxy for 'use_backend' rules */
5944 list_for_each_entry(srule, &curproxy->server_rules, list) {
5945 struct server *target = findserver(curproxy, srule->srv.name);
5946
5947 if (!target) {
5948 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5949 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5950 cfgerr++;
5951 continue;
5952 }
5953 free((void *)srule->srv.name);
5954 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005955 }
5956
Emeric Brunb982a3d2010-01-04 15:45:53 +01005957 /* find the target table for 'stick' rules */
5958 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5959 struct proxy *target;
5960
Emeric Brun1d33b292010-01-04 15:47:17 +01005961 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5962 if (mrule->flags & STK_IS_STORE)
5963 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5964
Emeric Brunb982a3d2010-01-04 15:45:53 +01005965 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005966 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005967 else
5968 target = curproxy;
5969
5970 if (!target) {
5971 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5972 curproxy->id, mrule->table.name);
5973 cfgerr++;
5974 }
5975 else if (target->table.size == 0) {
5976 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5977 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5978 cfgerr++;
5979 }
Willy Tarreau12785782012-04-27 21:37:17 +02005980 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5981 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005982 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5983 cfgerr++;
5984 }
5985 else {
5986 free((void *)mrule->table.name);
5987 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005988 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005989 }
5990 }
5991
5992 /* find the target table for 'store response' rules */
5993 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5994 struct proxy *target;
5995
Emeric Brun1d33b292010-01-04 15:47:17 +01005996 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5997
Emeric Brunb982a3d2010-01-04 15:45:53 +01005998 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005999 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006000 else
6001 target = curproxy;
6002
6003 if (!target) {
6004 Alert("Proxy '%s': unable to find store table '%s'.\n",
6005 curproxy->id, mrule->table.name);
6006 cfgerr++;
6007 }
6008 else if (target->table.size == 0) {
6009 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6010 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6011 cfgerr++;
6012 }
Willy Tarreau12785782012-04-27 21:37:17 +02006013 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6014 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006015 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6016 cfgerr++;
6017 }
6018 else {
6019 free((void *)mrule->table.name);
6020 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006021 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006022 }
6023 }
6024
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006025 /* find the target table for 'tcp-request' layer 4 rules */
6026 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6027 struct proxy *target;
6028
Willy Tarreau56123282010-08-06 19:06:56 +02006029 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006030 continue;
6031
6032 if (trule->act_prm.trk_ctr.table.n)
6033 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6034 else
6035 target = curproxy;
6036
6037 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006038 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6039 curproxy->id, trule->act_prm.trk_ctr.table.n,
6040 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006041 cfgerr++;
6042 }
6043 else if (target->table.size == 0) {
6044 Alert("Proxy '%s': table '%s' used but not configured.\n",
6045 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6046 cfgerr++;
6047 }
6048 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006049 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 +02006050 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6051 cfgerr++;
6052 }
6053 else {
6054 free(trule->act_prm.trk_ctr.table.n);
6055 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006056 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006057 * to pass a list of counters to track and allocate them right here using
6058 * stktable_alloc_data_type().
6059 */
6060 }
6061 }
6062
Willy Tarreaud1f96522010-08-03 19:34:32 +02006063 /* find the target table for 'tcp-request' layer 6 rules */
6064 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6065 struct proxy *target;
6066
Willy Tarreau56123282010-08-06 19:06:56 +02006067 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006068 continue;
6069
6070 if (trule->act_prm.trk_ctr.table.n)
6071 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6072 else
6073 target = curproxy;
6074
6075 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006076 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6077 curproxy->id, trule->act_prm.trk_ctr.table.n,
6078 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006079 cfgerr++;
6080 }
6081 else if (target->table.size == 0) {
6082 Alert("Proxy '%s': table '%s' used but not configured.\n",
6083 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6084 cfgerr++;
6085 }
6086 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006087 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 +02006088 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6089 cfgerr++;
6090 }
6091 else {
6092 free(trule->act_prm.trk_ctr.table.n);
6093 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006094 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006095 * to pass a list of counters to track and allocate them right here using
6096 * stktable_alloc_data_type().
6097 */
6098 }
6099 }
6100
Emeric Brun32da3c42010-09-23 18:39:19 +02006101 if (curproxy->table.peers.name) {
6102 struct peers *curpeers = peers;
6103
6104 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6105 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6106 free((void *)curproxy->table.peers.name);
6107 curproxy->table.peers.p = peers;
6108 break;
6109 }
6110 }
6111
6112 if (!curpeers) {
6113 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6114 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006115 free((void *)curproxy->table.peers.name);
6116 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006117 cfgerr++;
6118 }
6119 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006120 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6121 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006122 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006123 cfgerr++;
6124 }
6125 }
6126
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006127 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006128 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006129 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6130 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6131 "proxy", curproxy->id);
6132 cfgerr++;
6133 goto out_uri_auth_compat;
6134 }
6135
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006136 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006137 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006138 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006139 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006140
Willy Tarreau95fa4692010-02-01 13:05:50 +01006141 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6142 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006143
6144 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006145 uri_auth_compat_req[i++] = "realm";
6146 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6147 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006148
Willy Tarreau95fa4692010-02-01 13:05:50 +01006149 uri_auth_compat_req[i++] = "unless";
6150 uri_auth_compat_req[i++] = "{";
6151 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6152 uri_auth_compat_req[i++] = "}";
6153 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006154
Willy Tarreauff011f22011-01-06 17:51:27 +01006155 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6156 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006157 cfgerr++;
6158 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006159 }
6160
Willy Tarreauff011f22011-01-06 17:51:27 +01006161 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006162
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006163 if (curproxy->uri_auth->auth_realm) {
6164 free(curproxy->uri_auth->auth_realm);
6165 curproxy->uri_auth->auth_realm = NULL;
6166 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006167
6168 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006169 }
6170out_uri_auth_compat:
6171
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006172 cfgerr += acl_find_targets(curproxy);
6173
Willy Tarreau2738a142006-07-08 17:28:09 +02006174 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006175 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006176 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006177 (!curproxy->timeout.connect ||
6178 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006179 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006180 " | While not properly invalid, you will certainly encounter various problems\n"
6181 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006182 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006184 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006185 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006186
Willy Tarreau1fa31262007-12-03 00:36:16 +01006187 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6188 * We must still support older configurations, so let's find out whether those
6189 * parameters have been set or must be copied from contimeouts.
6190 */
6191 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006192 if (!curproxy->timeout.tarpit ||
6193 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006194 /* tarpit timeout not set. We search in the following order:
6195 * default.tarpit, curr.connect, default.connect.
6196 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006197 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006198 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006199 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006200 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006201 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006202 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006203 }
6204 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006205 (!curproxy->timeout.queue ||
6206 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006207 /* queue timeout not set. We search in the following order:
6208 * default.queue, curr.connect, default.connect.
6209 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006210 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006211 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006212 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006213 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006214 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006215 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006216 }
6217 }
6218
Willy Tarreau1620ec32011-08-06 17:05:02 +02006219 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006220 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6221 curproxy->check_req = (char *)malloc(curproxy->check_len);
6222 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006223 }
6224
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006225 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006226 if (curproxy->nb_req_cap) {
6227 if (curproxy->mode == PR_MODE_HTTP) {
6228 curproxy->req_cap_pool = create_pool("ptrcap",
6229 curproxy->nb_req_cap * sizeof(char *),
6230 MEM_F_SHARED);
6231 } else {
6232 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6233 proxy_type_str(curproxy), curproxy->id);
6234 err_code |= ERR_WARN;
6235 curproxy->to_log &= ~LW_REQHDR;
6236 curproxy->nb_req_cap = 0;
6237 }
6238 }
6239
6240 if (curproxy->nb_rsp_cap) {
6241 if (curproxy->mode == PR_MODE_HTTP) {
6242 curproxy->rsp_cap_pool = create_pool("ptrcap",
6243 curproxy->nb_rsp_cap * sizeof(char *),
6244 MEM_F_SHARED);
6245 } else {
6246 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6247 proxy_type_str(curproxy), curproxy->id);
6248 err_code |= ERR_WARN;
6249 curproxy->to_log &= ~LW_REQHDR;
6250 curproxy->nb_rsp_cap = 0;
6251 }
6252 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006253
Willy Tarreau196729e2012-05-31 19:30:26 +02006254 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006255 if (!(curproxy->cap & PR_CAP_FE)) {
6256 if (curproxy->logformat_string != default_http_log_format &&
6257 curproxy->logformat_string != default_tcp_log_format &&
6258 curproxy->logformat_string != clf_http_log_format)
6259 free(curproxy->logformat_string);
6260 curproxy->logformat_string = NULL;
6261 }
6262
Willy Tarreau196729e2012-05-31 19:30:26 +02006263 if (curproxy->logformat_string)
6264 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6265
6266 if (curproxy->uniqueid_format_string)
6267 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6268
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 /* first, we will invert the servers list order */
6270 newsrv = NULL;
6271 while (curproxy->srv) {
6272 struct server *next;
6273
6274 next = curproxy->srv->next;
6275 curproxy->srv->next = newsrv;
6276 newsrv = curproxy->srv;
6277 if (!next)
6278 break;
6279 curproxy->srv = next;
6280 }
6281
Willy Tarreaudd701652010-05-25 23:03:02 +02006282 /* assign automatic UIDs to servers which don't have one yet */
6283 next_id = 1;
6284 newsrv = curproxy->srv;
6285 while (newsrv != NULL) {
6286 if (!newsrv->puid) {
6287 /* server ID not set, use automatic numbering with first
6288 * spare entry starting with next_svid.
6289 */
6290 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6291 newsrv->conf.id.key = newsrv->puid = next_id;
6292 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6293 }
6294 next_id++;
6295 newsrv = newsrv->next;
6296 }
6297
Willy Tarreau20697042007-11-15 23:26:18 +01006298 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006299 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006300
Willy Tarreau62c3be22012-01-20 13:12:32 +01006301 /*
6302 * If this server supports a maxconn parameter, it needs a dedicated
6303 * tasks to fill the emptied slots when a connection leaves.
6304 * Also, resolve deferred tracking dependency if needed.
6305 */
6306 newsrv = curproxy->srv;
6307 while (newsrv != NULL) {
6308 if (newsrv->minconn > newsrv->maxconn) {
6309 /* Only 'minconn' was specified, or it was higher than or equal
6310 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6311 * this will avoid further useless expensive computations.
6312 */
6313 newsrv->maxconn = newsrv->minconn;
6314 } else if (newsrv->maxconn && !newsrv->minconn) {
6315 /* minconn was not specified, so we set it to maxconn */
6316 newsrv->minconn = newsrv->maxconn;
6317 }
6318
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006319#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006320 if (newsrv->use_ssl || newsrv->check.use_ssl)
6321 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006322#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006323
Willy Tarreau62c3be22012-01-20 13:12:32 +01006324 if (newsrv->trackit) {
6325 struct proxy *px;
6326 struct server *srv;
6327 char *pname, *sname;
6328
6329 pname = newsrv->trackit;
6330 sname = strrchr(pname, '/');
6331
6332 if (sname)
6333 *sname++ = '\0';
6334 else {
6335 sname = pname;
6336 pname = NULL;
6337 }
6338
6339 if (pname) {
6340 px = findproxy(pname, PR_CAP_BE);
6341 if (!px) {
6342 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6343 proxy_type_str(curproxy), curproxy->id,
6344 newsrv->id, pname);
6345 cfgerr++;
6346 goto next_srv;
6347 }
6348 } else
6349 px = curproxy;
6350
6351 srv = findserver(px, sname);
6352 if (!srv) {
6353 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6354 proxy_type_str(curproxy), curproxy->id,
6355 newsrv->id, sname);
6356 cfgerr++;
6357 goto next_srv;
6358 }
6359
6360 if (!(srv->state & SRV_CHECKED)) {
6361 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6362 "tracking as it does not have checks enabled.\n",
6363 proxy_type_str(curproxy), curproxy->id,
6364 newsrv->id, px->id, srv->id);
6365 cfgerr++;
6366 goto next_srv;
6367 }
6368
6369 if (curproxy != px &&
6370 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6371 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6372 "tracking: disable-on-404 option inconsistency.\n",
6373 proxy_type_str(curproxy), curproxy->id,
6374 newsrv->id, px->id, srv->id);
6375 cfgerr++;
6376 goto next_srv;
6377 }
6378
6379 /* if the other server is forced disabled, we have to do the same here */
6380 if (srv->state & SRV_MAINTAIN) {
6381 newsrv->state |= SRV_MAINTAIN;
6382 newsrv->state &= ~SRV_RUNNING;
6383 newsrv->health = 0;
6384 }
6385
6386 newsrv->track = srv;
6387 newsrv->tracknext = srv->tracknext;
6388 srv->tracknext = newsrv;
6389
6390 free(newsrv->trackit);
6391 newsrv->trackit = NULL;
6392 }
6393 next_srv:
6394 newsrv = newsrv->next;
6395 }
6396
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006397 /* We have to initialize the server lookup mechanism depending
6398 * on what LB algorithm was choosen.
6399 */
6400
6401 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6402 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6403 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006404 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6405 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6406 init_server_map(curproxy);
6407 } else {
6408 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6409 fwrr_init_server_groups(curproxy);
6410 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006411 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006412
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006413 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006414 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6415 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6416 fwlc_init_server_tree(curproxy);
6417 } else {
6418 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6419 fas_init_server_tree(curproxy);
6420 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006421 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006422
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006423 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006424 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6425 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6426 chash_init_server_tree(curproxy);
6427 } else {
6428 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6429 init_server_map(curproxy);
6430 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006431 break;
6432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433
6434 if (curproxy->options & PR_O_LOGASAP)
6435 curproxy->to_log &= ~LW_BYTES;
6436
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006437 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006438 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006439 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6440 proxy_type_str(curproxy), curproxy->id);
6441 err_code |= ERR_WARN;
6442 }
6443
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006444 if (curproxy->mode != PR_MODE_HTTP) {
6445 int optnum;
6446
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006447 if (curproxy->uri_auth) {
6448 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6449 proxy_type_str(curproxy), curproxy->id);
6450 err_code |= ERR_WARN;
6451 curproxy->uri_auth = NULL;
6452 }
6453
Willy Tarreau87cf5142011-08-19 22:57:24 +02006454 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006455 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6456 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6457 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006458 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006459 }
6460
6461 if (curproxy->options & PR_O_ORGTO) {
6462 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6463 "originalto", proxy_type_str(curproxy), curproxy->id);
6464 err_code |= ERR_WARN;
6465 curproxy->options &= ~PR_O_ORGTO;
6466 }
6467
6468 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6469 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6470 (curproxy->cap & cfg_opts[optnum].cap) &&
6471 (curproxy->options & cfg_opts[optnum].val)) {
6472 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6473 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6474 err_code |= ERR_WARN;
6475 curproxy->options &= ~cfg_opts[optnum].val;
6476 }
6477 }
6478
6479 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6480 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6481 (curproxy->cap & cfg_opts2[optnum].cap) &&
6482 (curproxy->options2 & cfg_opts2[optnum].val)) {
6483 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6484 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6485 err_code |= ERR_WARN;
6486 curproxy->options2 &= ~cfg_opts2[optnum].val;
6487 }
6488 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006489
Willy Tarreauefa5f512010-03-30 20:13:29 +02006490#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006491 if (curproxy->bind_hdr_occ) {
6492 curproxy->bind_hdr_occ = 0;
6493 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6494 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6495 err_code |= ERR_WARN;
6496 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006497#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006498 }
6499
Willy Tarreaubaaee002006-06-26 02:48:02 +02006500 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006501 * ensure that we're not cross-dressing a TCP server into HTTP.
6502 */
6503 newsrv = curproxy->srv;
6504 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006505 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006506 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6507 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006508 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006509 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006510
Willy Tarreau0cec3312011-10-31 13:49:26 +01006511 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6512 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6513 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6514 err_code |= ERR_WARN;
6515 }
6516
Willy Tarreauefa5f512010-03-30 20:13:29 +02006517#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006518 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6519 newsrv->bind_hdr_occ = 0;
6520 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6521 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6522 err_code |= ERR_WARN;
6523 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006524#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006525 newsrv = newsrv->next;
6526 }
6527
Willy Tarreauc1a21672009-08-16 22:37:44 +02006528 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006529 if (!curproxy->accept)
6530 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006531
Willy Tarreauc1a21672009-08-16 22:37:44 +02006532 if (curproxy->tcp_req.inspect_delay ||
6533 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006534 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006535
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006536 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006537 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006538 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006539 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006540
6541 /* both TCP and HTTP must check switching rules */
6542 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6543 }
6544
6545 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006546 if (curproxy->tcp_req.inspect_delay ||
6547 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6548 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6549
Emeric Brun97679e72010-09-23 17:56:44 +02006550 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6551 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6552
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006553 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006554 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006555 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006556 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006557
6558 /* If the backend does requires RDP cookie persistence, we have to
6559 * enable the corresponding analyser.
6560 */
6561 if (curproxy->options2 & PR_O2_RDPC_PRST)
6562 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6563 }
6564
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006565 /* Configure SSL for each bind line.
6566 * Note: if configuration fails at some point, the ->ctx member
6567 * remains NULL so that listeners can later detach.
6568 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006569 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6570 if (!bind_conf->is_ssl)
6571 continue;
6572#ifdef USE_OPENSSL
6573 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006574 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006575 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006576 cfgerr++;
6577 continue;
6578 }
6579
Emeric Brun4b3091e2012-09-24 15:48:52 +02006580 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006581 Alert("Unable to allocate SSL session cache.\n");
6582 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006583 continue;
6584 }
6585
Emeric Brunfc0421f2012-09-07 17:30:07 +02006586 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006587 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006588#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006589 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006590
Willy Tarreaue6b98942007-10-29 01:09:36 +01006591 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006592 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006593 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006594 if (!listener->luid) {
6595 /* listener ID not set, use automatic numbering with first
6596 * spare entry starting with next_luid.
6597 */
6598 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6599 listener->conf.id.key = listener->luid = next_id;
6600 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006601 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006602 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006603
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006604 /* enable separate counters */
6605 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6606 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6607 if (!listener->name) {
6608 sprintf(trash, "sock-%d", listener->luid);
6609 listener->name = strdup(trash);
6610 }
6611 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006612
Willy Tarreaue6b98942007-10-29 01:09:36 +01006613 if (curproxy->options & PR_O_TCP_NOLING)
6614 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006615 if (!listener->maxconn)
6616 listener->maxconn = curproxy->maxconn;
6617 if (!listener->backlog)
6618 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006619 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006620 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006621 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006622 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006623
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006624 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6625 listener->options |= LI_O_TCP_RULES;
6626
Willy Tarreaude3041d2010-05-31 10:56:17 +02006627 if (curproxy->mon_mask.s_addr)
6628 listener->options |= LI_O_CHK_MONNET;
6629
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006630 /* smart accept mode is automatic in HTTP mode */
6631 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006632 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006633 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6634 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006635 }
6636
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006637 /* Release unused SSL configs */
6638 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6639 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006640 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006641#ifdef USE_OPENSSL
6642 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006643 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006644 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006645 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006646 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006647#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006648 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006649
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006650 /* Check multi-process mode compatibility for the current proxy */
6651 if (global.nbproc > 1) {
6652 int nbproc = 0;
6653 if (curproxy->bind_proc) {
6654 int proc;
6655 for (proc = 0; proc < global.nbproc; proc++) {
6656 if (curproxy->bind_proc & (1 << proc)) {
6657 nbproc++;
6658 }
6659 }
6660 } else {
6661 nbproc = global.nbproc;
6662 }
6663 if (curproxy->table.peers.name) {
6664 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6665 curproxy->id);
6666 cfgerr++;
6667 }
6668 if (nbproc > 1) {
6669 if (curproxy->uri_auth) {
6670 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6671 curproxy->id);
6672 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6673 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6674 curproxy->id);
6675 }
6676 }
6677 if (curproxy->appsession_name) {
6678 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6679 curproxy->id);
6680 }
6681 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6682 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6683 curproxy->id);
6684 }
6685 }
6686 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006687
6688 /* create the task associated with the proxy */
6689 curproxy->task = task_new();
6690 if (curproxy->task) {
6691 curproxy->task->context = curproxy;
6692 curproxy->task->process = manage_proxy;
6693 /* no need to queue, it will be done automatically if some
6694 * listener gets limited.
6695 */
6696 curproxy->task->expire = TICK_ETERNITY;
6697 } else {
6698 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6699 curproxy->id);
6700 cfgerr++;
6701 }
6702
Willy Tarreaubaaee002006-06-26 02:48:02 +02006703 curproxy = curproxy->next;
6704 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006705
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006706 /* Check multi-process mode compatibility */
6707 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006708 if (global.stats_fe && !global.stats_fe->bind_proc) {
6709 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 +01006710 }
6711 }
6712
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006713 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6714 struct auth_users *curuser;
6715 int g;
6716
6717 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6718 unsigned int group_mask = 0;
6719 char *group = NULL;
6720
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006721 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006722 continue;
6723
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006724 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006725
6726 for (g = 0; g < curuserlist->grpcnt; g++)
6727 if (!strcmp(curuserlist->groups[g], group))
6728 break;
6729
6730 if (g == curuserlist->grpcnt) {
6731 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6732 curuserlist->name, group, curuser->user);
6733 err_code |= ERR_ALERT | ERR_FATAL;
6734 goto out;
6735 }
6736
6737 group_mask |= (1 << g);
6738 }
6739
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006740 free(curuser->u.groups);
6741 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 }
6743
6744 for (g = 0; g < curuserlist->grpcnt; g++) {
6745 char *user = NULL;
6746
6747 if (!curuserlist->groupusers[g])
6748 continue;
6749
6750 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6751 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6752 if (!strcmp(curuser->user, user))
6753 break;
6754
6755 if (!curuser) {
6756 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6757 curuserlist->name, user, curuserlist->groups[g]);
6758 err_code |= ERR_ALERT | ERR_FATAL;
6759 goto out;
6760 }
6761
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006762 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006763 }
6764
6765 free(curuserlist->groupusers[g]);
6766 }
6767
6768 free(curuserlist->groupusers);
6769
6770#ifdef DEBUG_AUTH
6771 for (g = 0; g < curuserlist->grpcnt; g++) {
6772 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6773
6774 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006775 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006776 fprintf(stderr, " %s", curuser->user);
6777 }
6778
6779 fprintf(stderr, "\n");
6780 }
6781#endif
6782
Willy Tarreaufbb78422011-06-05 15:38:35 +02006783 }
6784
6785 /* automatically compute fullconn if not set. We must not do it in the
6786 * loop above because cross-references are not yet fully resolved.
6787 */
6788 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6789 /* If <fullconn> is not set, let's set it to 10% of the sum of
6790 * the possible incoming frontend's maxconns.
6791 */
6792 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6793 struct proxy *fe;
6794 int total = 0;
6795
6796 /* sum up the number of maxconns of frontends which
6797 * reference this backend at least once or which are
6798 * the same one ('listen').
6799 */
6800 for (fe = proxy; fe; fe = fe->next) {
6801 struct switching_rule *rule;
6802 struct hdr_exp *exp;
6803 int found = 0;
6804
6805 if (!(fe->cap & PR_CAP_FE))
6806 continue;
6807
6808 if (fe == curproxy) /* we're on a "listen" instance */
6809 found = 1;
6810
6811 if (fe->defbe.be == curproxy) /* "default_backend" */
6812 found = 1;
6813
6814 /* check if a "use_backend" rule matches */
6815 if (!found) {
6816 list_for_each_entry(rule, &fe->switching_rules, list) {
6817 if (rule->be.backend == curproxy) {
6818 found = 1;
6819 break;
6820 }
6821 }
6822 }
6823
6824 /* check if a "reqsetbe" rule matches */
6825 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6826 if (exp->action == ACT_SETBE &&
6827 (struct proxy *)exp->replace == curproxy) {
6828 found = 1;
6829 break;
6830 }
6831 }
6832
6833 /* now we've checked all possible ways to reference a backend
6834 * from a frontend.
6835 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006836 if (!found)
6837 continue;
6838 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006839 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006840 /* we have the sum of the maxconns in <total>. We only
6841 * keep 10% of that sum to set the default fullconn, with
6842 * a hard minimum of 1 (to avoid a divide by zero).
6843 */
6844 curproxy->fullconn = (total + 9) / 10;
6845 if (!curproxy->fullconn)
6846 curproxy->fullconn = 1;
6847 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006848 }
6849
Willy Tarreau056f5682010-06-06 15:51:11 +02006850 /* initialize stick-tables on backend capable proxies. This must not
6851 * be done earlier because the data size may be discovered while parsing
6852 * other proxies.
6853 */
6854 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006855 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006856
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006857 /*
6858 * Recount currently required checks.
6859 */
6860
6861 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6862 int optnum;
6863
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006864 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6865 if (curproxy->options & cfg_opts[optnum].val)
6866 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006867
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006868 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6869 if (curproxy->options2 & cfg_opts2[optnum].val)
6870 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006871 }
6872
Willy Tarreau122541c2011-09-07 21:24:49 +02006873 if (peers) {
6874 struct peers *curpeers = peers, **last;
6875 struct peer *p, *pb;
6876
6877 /* Remove all peers sections which don't have a valid listener.
6878 * This can happen when a peers section is never referenced and
6879 * does not contain a local peer.
6880 */
6881 last = &peers;
6882 while (*last) {
6883 curpeers = *last;
6884 if (curpeers->peers_fe) {
6885 last = &curpeers->next;
6886 continue;
6887 }
6888
6889 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6890 curpeers->id, localpeer);
6891
6892 p = curpeers->remote;
6893 while (p) {
6894 pb = p->next;
6895 free(p->id);
6896 free(p);
6897 p = pb;
6898 }
6899
6900 /* Destroy and unlink this curpeers section.
6901 * Note: curpeers is backed up into *last.
6902 */
6903 free(curpeers->id);
6904 curpeers = curpeers->next;
6905 free(*last);
6906 *last = curpeers;
6907 }
6908 }
6909
Willy Tarreauac1932d2011-10-24 19:14:41 +02006910 if (!global.tune.max_http_hdr)
6911 global.tune.max_http_hdr = MAX_HTTP_HDR;
6912
Willy Tarreau34eb6712011-10-24 18:15:04 +02006913 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006914 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006915 MEM_F_SHARED);
6916
Willy Tarreaubb925012009-07-23 13:36:36 +02006917 if (cfgerr > 0)
6918 err_code |= ERR_ALERT | ERR_FATAL;
6919 out:
6920 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921}
6922
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006923/*
6924 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6925 * parsing sessions.
6926 */
6927void cfg_register_keywords(struct cfg_kw_list *kwl)
6928{
6929 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6930}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006932/*
6933 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6934 */
6935void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6936{
6937 LIST_DEL(&kwl->list);
6938 LIST_INIT(&kwl->list);
6939}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006940
6941/*
6942 * Local variables:
6943 * c-indent-level: 8
6944 * c-basic-offset: 8
6945 * End:
6946 */