blob: 6c58e43a0ba032ea42cea9efb5394b4c8e2b3da8 [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], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100518 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100521 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100523 else if (!strcmp(args[0], "nosplice")) {
524 global.tune.options &= ~GTUNE_USE_SPLICE;
525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200526 else if (!strcmp(args[0], "quiet")) {
527 global.mode |= MODE_QUIET;
528 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200529 else if (!strcmp(args[0], "tune.maxpollevents")) {
530 if (global.tune.maxpollevents != 0) {
531 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200532 err_code |= ERR_ALERT;
533 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200534 }
535 if (*(args[1]) == 0) {
536 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200537 err_code |= ERR_ALERT | ERR_FATAL;
538 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200539 }
540 global.tune.maxpollevents = atol(args[1]);
541 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100542 else if (!strcmp(args[0], "tune.maxaccept")) {
543 if (global.tune.maxaccept != 0) {
544 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200545 err_code |= ERR_ALERT;
546 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100547 }
548 if (*(args[1]) == 0) {
549 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200550 err_code |= ERR_ALERT | ERR_FATAL;
551 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100552 }
553 global.tune.maxaccept = atol(args[1]);
554 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200555 else if (!strcmp(args[0], "tune.chksize")) {
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.tune.chksize = atol(args[1]);
562 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563#ifdef USE_OPENSSL
564 else if (!strcmp(args[0], "tune.sslcachesize")) {
565 if (*(args[1]) == 0) {
566 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
569 }
570 global.tune.sslcachesize = atol(args[1]);
571 }
572#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200573 else if (!strcmp(args[0], "tune.bufsize")) {
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579 global.tune.bufsize = atol(args[1]);
580 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
581 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100582 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200583 }
584 else if (!strcmp(args[0], "tune.maxrewrite")) {
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.maxrewrite = atol(args[1]);
591 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
592 global.tune.maxrewrite = global.tune.bufsize / 2;
593 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100594 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
595 if (global.tune.client_rcvbuf != 0) {
596 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT;
598 goto out;
599 }
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.client_rcvbuf = atol(args[1]);
606 }
607 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
608 if (global.tune.server_rcvbuf != 0) {
609 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
610 err_code |= ERR_ALERT;
611 goto out;
612 }
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
617 }
618 global.tune.server_rcvbuf = atol(args[1]);
619 }
620 else if (!strcmp(args[0], "tune.sndbuf.client")) {
621 if (global.tune.client_sndbuf != 0) {
622 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
623 err_code |= ERR_ALERT;
624 goto out;
625 }
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630 }
631 global.tune.client_sndbuf = atol(args[1]);
632 }
633 else if (!strcmp(args[0], "tune.sndbuf.server")) {
634 if (global.tune.server_sndbuf != 0) {
635 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
636 err_code |= ERR_ALERT;
637 goto out;
638 }
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.server_sndbuf = atol(args[1]);
645 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200646 else if (!strcmp(args[0], "tune.pipesize")) {
647 if (*(args[1]) == 0) {
648 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 global.tune.pipesize = atol(args[1]);
653 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200654 else if (!strcmp(args[0], "tune.http.maxhdr")) {
655 if (*(args[1]) == 0) {
656 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
657 err_code |= ERR_ALERT | ERR_FATAL;
658 goto out;
659 }
660 global.tune.max_http_hdr = atol(args[1]);
661 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100662 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
663#ifdef USE_ZLIB
664 if (*args[1]) {
665 global.tune.zlibmemlevel = atoi(args[1]);
666 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
667 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
668 file, linenum, args[0]);
669 err_code |= ERR_ALERT | ERR_FATAL;
670 goto out;
671 }
672 } else {
673 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
674 file, linenum, args[0]);
675 err_code |= ERR_ALERT | ERR_FATAL;
676 goto out;
677 }
678#else
679 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682#endif
683 }
684 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
685#ifdef USE_ZLIB
686 if (*args[1]) {
687 global.tune.zlibwindowsize = atoi(args[1]);
688 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
689 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
690 file, linenum, args[0]);
691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
693 }
694 } else {
695 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
696 file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700#else
701 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704#endif
705 }
William Lallemandf3747832012-11-09 12:33:10 +0100706 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
707 if (*args[1]) {
708 global.tune.comp_maxlevel = atoi(args[1]);
709 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
710 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
711 file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 } else {
716 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
717 file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 else if (!strcmp(args[0], "uid")) {
723 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200724 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733 global.uid = atol(args[1]);
734 }
735 else if (!strcmp(args[0], "gid")) {
736 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200737 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200738 err_code |= ERR_ALERT;
739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 }
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 global.gid = atol(args[1]);
747 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200748 /* user/group name handling */
749 else if (!strcmp(args[0], "user")) {
750 struct passwd *ha_user;
751 if (global.uid != 0) {
752 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200755 }
756 errno = 0;
757 ha_user = getpwnam(args[1]);
758 if (ha_user != NULL) {
759 global.uid = (int)ha_user->pw_uid;
760 }
761 else {
762 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 +0200763 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200764 }
765 }
766 else if (!strcmp(args[0], "group")) {
767 struct group *ha_group;
768 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200769 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT;
771 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 }
773 errno = 0;
774 ha_group = getgrnam(args[1]);
775 if (ha_group != NULL) {
776 global.gid = (int)ha_group->gr_gid;
777 }
778 else {
779 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 +0200780 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200781 }
782 }
783 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 else if (!strcmp(args[0], "nbproc")) {
785 if (global.nbproc != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 }
795 global.nbproc = atol(args[1]);
796 }
797 else if (!strcmp(args[0], "maxconn")) {
798 if (global.maxconn != 0) {
799 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 }
803 if (*(args[1]) == 0) {
804 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT | ERR_FATAL;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 global.maxconn = atol(args[1]);
809#ifdef SYSTEM_MAXCONN
810 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
811 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);
812 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 }
815#endif /* SYSTEM_MAXCONN */
816 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200817 else if (!strcmp(args[0], "maxsslconn")) {
818#ifdef USE_OPENSSL
819 if (*(args[1]) == 0) {
820 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT | ERR_FATAL;
822 goto out;
823 }
824 global.maxsslconn = atol(args[1]);
825#else
Emeric Brun0914df82012-10-02 18:45:42 +0200826 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200829#endif
830 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200831 else if (!strcmp(args[0], "maxconnrate")) {
832 if (global.cps_lim != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
834 err_code |= ERR_ALERT;
835 goto out;
836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.cps_lim = atol(args[1]);
843 }
William Lallemandd85f9172012-11-09 17:05:39 +0100844 else if (!strcmp(args[0], "maxcomprate")) {
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
849 }
850 global.comp_rate_lim = atoi(args[1]) * 1024;
851 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100852 else if (!strcmp(args[0], "maxpipes")) {
853 if (global.maxpipes != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT;
856 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100862 }
863 global.maxpipes = atol(args[1]);
864 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100865 else if (!strcmp(args[0], "maxzlibmem")) {
866 if (*(args[1]) == 0) {
867 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871 global.maxzlibmem = atol(args[1]);
872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 else if (!strcmp(args[0], "ulimit-n")) {
874 if (global.rlimit_nofile != 0) {
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 an integer 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.rlimit_nofile = atol(args[1]);
885 }
886 else if (!strcmp(args[0], "chroot")) {
887 if (global.chroot != NULL) {
888 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 err_code |= ERR_ALERT;
890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891 }
892 if (*(args[1]) == 0) {
893 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 }
897 global.chroot = strdup(args[1]);
898 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200899 else if (!strcmp(args[0], "description")) {
900 int i, len=0;
901 char *d;
902
903 if (!*args[1]) {
904 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
905 file, linenum, args[0]);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909
910 for(i=1; *args[i]; i++)
911 len += strlen(args[i])+1;
912
913 if (global.desc)
914 free(global.desc);
915
916 global.desc = d = (char *)calloc(1, len);
917
918 d += sprintf(d, "%s", args[1]);
919 for(i=2; *args[i]; i++)
920 d += sprintf(d, " %s", args[i]);
921 }
922 else if (!strcmp(args[0], "node")) {
923 int i;
924 char c;
925
926 for (i=0; args[1][i]; i++) {
927 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100928 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
929 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200930 break;
931 }
932
933 if (!i || args[1][i]) {
934 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
935 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
936 file, linenum, args[0]);
937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto out;
939 }
940
941 if (global.node)
942 free(global.node);
943
944 global.node = strdup(args[1]);
945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 else if (!strcmp(args[0], "pidfile")) {
947 if (global.pidfile != NULL) {
948 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT;
950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
952 if (*(args[1]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 }
957 global.pidfile = strdup(args[1]);
958 }
Emeric Bruned760922010-10-22 17:59:25 +0200959 else if (!strcmp(args[0], "unix-bind")) {
960 int cur_arg = 1;
961 while (*(args[cur_arg])) {
962 if (!strcmp(args[cur_arg], "prefix")) {
963 if (global.unix_bind.prefix != NULL) {
964 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
965 err_code |= ERR_ALERT;
966 cur_arg += 2;
967 continue;
968 }
969
970 if (*(args[cur_arg+1]) == 0) {
971 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 global.unix_bind.prefix = strdup(args[cur_arg+1]);
976 cur_arg += 2;
977 continue;
978 }
979
980 if (!strcmp(args[cur_arg], "mode")) {
981
982 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
983 cur_arg += 2;
984 continue;
985 }
986
987 if (!strcmp(args[cur_arg], "uid")) {
988
989 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
990 cur_arg += 2;
991 continue;
992 }
993
994 if (!strcmp(args[cur_arg], "gid")) {
995
996 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
997 cur_arg += 2;
998 continue;
999 }
1000
1001 if (!strcmp(args[cur_arg], "user")) {
1002 struct passwd *user;
1003
1004 user = getpwnam(args[cur_arg + 1]);
1005 if (!user) {
1006 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1007 file, linenum, args[0], args[cur_arg + 1 ]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010 }
1011
1012 global.unix_bind.ux.uid = user->pw_uid;
1013 cur_arg += 2;
1014 continue;
1015 }
1016
1017 if (!strcmp(args[cur_arg], "group")) {
1018 struct group *group;
1019
1020 group = getgrnam(args[cur_arg + 1]);
1021 if (!group) {
1022 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1023 file, linenum, args[0], args[cur_arg + 1 ]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027
1028 global.unix_bind.ux.gid = group->gr_gid;
1029 cur_arg += 2;
1030 continue;
1031 }
1032
Willy Tarreaub48f9582011-09-05 01:17:06 +02001033 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001034 file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038 }
William Lallemand0f99e342011-10-12 17:50:54 +02001039 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1040 /* delete previous herited or defined syslog servers */
1041 struct logsrv *back;
1042 struct logsrv *tmp;
1043
1044 if (*(args[1]) != 0) {
1045 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049
1050 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1051 LIST_DEL(&tmp->list);
1052 free(tmp);
1053 }
1054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001056 struct logsrv *logsrv;
1057
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 if (*(args[1]) == 0 || *(args[2]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
William Lallemand0f99e342011-10-12 17:50:54 +02001063
1064 logsrv = calloc(1, sizeof(struct logsrv));
1065
1066 logsrv->facility = get_log_facility(args[2]);
1067 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001069 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001070 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 }
1072
William Lallemand0f99e342011-10-12 17:50:54 +02001073 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001075 logsrv->level = get_log_level(args[3]);
1076 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001078 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001079 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001080 }
1081 }
1082
William Lallemand0f99e342011-10-12 17:50:54 +02001083 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001084 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001085 logsrv->minlvl = get_log_level(args[4]);
1086 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001087 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001089 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001090 }
1091 }
1092
Robert Tsai81ae1952007-12-05 10:47:29 +01001093 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001094 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001095 if (!sk) {
1096 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001097 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001098 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001099 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001100 goto out;
1101 }
William Lallemand0f99e342011-10-12 17:50:54 +02001102 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001103 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001104 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001105 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001106 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1107 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001108 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001109 goto out;
1110 }
William Lallemand0f99e342011-10-12 17:50:54 +02001111 logsrv->addr = *sk;
1112 if (!get_host_port(&logsrv->addr))
1113 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115
William Lallemand0f99e342011-10-12 17:50:54 +02001116 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001117 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001118 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1119 char *name;
1120 int len;
1121
1122 if (global.log_send_hostname != NULL) {
1123 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1124 err_code |= ERR_ALERT;
1125 goto out;
1126 }
1127
1128 if (*(args[1]))
1129 name = args[1];
1130 else
1131 name = hostname;
1132
1133 len = strlen(name);
1134
1135 /* We'll add a space after the name to respect the log format */
1136 free(global.log_send_hostname);
1137 global.log_send_hostname = malloc(len + 2);
1138 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1139 }
Kevinm48936af2010-12-22 16:08:21 +00001140 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1141 if (*(args[1]) == 0) {
1142 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1143 err_code |= ERR_ALERT | ERR_FATAL;
1144 goto out;
1145 }
1146 free(global.log_tag);
1147 global.log_tag = strdup(args[1]);
1148 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001149 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1150 if (global.spread_checks != 0) {
1151 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT;
1153 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001154 }
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001159 }
1160 global.spread_checks = atol(args[1]);
1161 if (global.spread_checks < 0 || global.spread_checks > 50) {
1162 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001163 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 }
1166 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001167 struct cfg_kw_list *kwl;
1168 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001169 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001170
1171 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1172 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1173 if (kwl->kw[index].section != CFG_GLOBAL)
1174 continue;
1175 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001176 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001177 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001178 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001179 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001180 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001181 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001182 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001183 err_code |= ERR_WARN;
1184 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001185 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001186 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001187 }
1188 }
1189 }
1190
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001194
Willy Tarreau058e9072009-07-20 09:30:05 +02001195 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001196 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001197 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198}
1199
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001200void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001202 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 defproxy.mode = PR_MODE_TCP;
1204 defproxy.state = PR_STNEW;
1205 defproxy.maxconn = cfg_maxpconn;
1206 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001207
1208 defproxy.defsrv.inter = DEF_CHKINTR;
1209 defproxy.defsrv.fastinter = 0;
1210 defproxy.defsrv.downinter = 0;
1211 defproxy.defsrv.rise = DEF_RISETIME;
1212 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001213 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001214 defproxy.defsrv.maxqueue = 0;
1215 defproxy.defsrv.minconn = 0;
1216 defproxy.defsrv.maxconn = 0;
1217 defproxy.defsrv.slowstart = 0;
1218 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1219 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1220 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001221}
1222
Willy Tarreauade5ec42010-01-28 19:33:49 +01001223
1224static int create_cond_regex_rule(const char *file, int line,
1225 struct proxy *px, int dir, int action, int flags,
1226 const char *cmd, const char *reg, const char *repl,
1227 const char **cond_start)
1228{
1229 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001230 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001231 const char *err;
1232 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001233 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001234
1235 if (px == &defproxy) {
1236 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto err;
1239 }
1240
1241 if (*reg == 0) {
1242 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto err;
1245 }
1246
1247 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1248 err_code |= ERR_WARN;
1249
Willy Tarreau5321c422010-01-28 20:35:13 +01001250 if (cond_start &&
1251 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001252 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1253 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1254 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto err;
1257 }
1258 }
1259 else if (cond_start && **cond_start) {
1260 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1261 file, line, cmd, *cond_start);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto err;
1264 }
1265
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001266 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001267 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001268 else
1269 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001270
Willy Tarreauade5ec42010-01-28 19:33:49 +01001271 preg = calloc(1, sizeof(regex_t));
1272 if (!preg) {
1273 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1274 err_code = ERR_ALERT | ERR_FATAL;
1275 goto err;
1276 }
1277
1278 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1279 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1280 err_code = ERR_ALERT | ERR_FATAL;
1281 goto err;
1282 }
1283
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001284 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001285 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001286 if (repl && err) {
1287 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1288 file, line, cmd, *err);
1289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto err;
1291 }
1292
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001293 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001294 err_code |= ERR_WARN;
1295
Willy Tarreauf4068b62012-05-08 17:37:49 +02001296 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001297 return err_code;
1298 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001299 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001300 free(preg);
1301 return err_code;
1302}
1303
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001305 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001306 * Returns the error code, 0 if OK, or any combination of :
1307 * - ERR_ABORT: must abort ASAP
1308 * - ERR_FATAL: we can continue parsing but not start the service
1309 * - ERR_WARN: a warning has been emitted
1310 * - ERR_ALERT: an alert has been emitted
1311 * Only the two first ones can stop processing, the two others are just
1312 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001314int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1315{
1316 static struct peers *curpeers = NULL;
1317 struct peer *newpeer = NULL;
1318 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001319 struct bind_conf *bind_conf;
1320 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001321 int err_code = 0;
1322
1323 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1324
1325 err = invalid_char(args[1]);
1326 if (err) {
1327 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1328 file, linenum, *err, args[0], args[1]);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 }
1331
1332 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1333 /*
1334 * If there are two proxies with the same name only following
1335 * combinations are allowed:
1336 */
1337 if (strcmp(curpeers->id, args[1]) == 0) {
1338 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1339 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1340 err_code |= ERR_WARN;
1341 }
1342 }
1343
1344 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1345 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1346 err_code |= ERR_ALERT | ERR_ABORT;
1347 goto out;
1348 }
1349
1350 curpeers->next = peers;
1351 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001352 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001353 curpeers->conf.line = linenum;
1354 curpeers->last_change = now.tv_sec;
1355 curpeers->id = strdup(args[1]);
1356 }
1357 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1358 char *rport, *raddr;
1359 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001360 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001361 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001362
1363 if (!*args[2]) {
1364 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1365 file, linenum, args[0]);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
1368 }
1369
1370 err = invalid_char(args[1]);
1371 if (err) {
1372 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1373 file, linenum, *err, args[1]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376 }
1377
1378 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1380 err_code |= ERR_ALERT | ERR_ABORT;
1381 goto out;
1382 }
1383
1384 /* the peers are linked backwards first */
1385 curpeers->count++;
1386 newpeer->next = curpeers->remote;
1387 curpeers->remote = newpeer;
1388 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001389 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001390 newpeer->conf.line = linenum;
1391
1392 newpeer->last_change = now.tv_sec;
1393 newpeer->id = strdup(args[1]);
1394
1395 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001396 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001397 if (rport) {
1398 *rport++ = 0;
1399 realport = atol(rport);
1400 }
1401 if (!realport) {
1402 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1403 err_code |= ERR_ALERT | ERR_FATAL;
1404 goto out;
1405 }
1406
Willy Tarreaufab5a432011-03-04 15:31:53 +01001407 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001408 free(raddr);
1409 if (!sk) {
1410 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1411 err_code |= ERR_ALERT | ERR_FATAL;
1412 goto out;
1413 }
1414 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001415 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001416 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001417 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001418
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001419 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001420 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1421 file, linenum, newpeer->addr.ss_family, args[2]);
1422 err_code |= ERR_ALERT | ERR_FATAL;
1423 goto out;
1424 }
1425
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001426 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001427
1428 if (strcmp(newpeer->id, localpeer) == 0) {
1429 /* Current is local peer, it define a frontend */
1430 newpeer->local = 1;
1431
1432 if (!curpeers->peers_fe) {
1433 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1434 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1435 err_code |= ERR_ALERT | ERR_ABORT;
1436 goto out;
1437 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001438
Willy Tarreau237250c2011-07-29 01:49:03 +02001439 init_new_proxy(curpeers->peers_fe);
1440 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001441
1442 curpeers->peers_fe->last_change = now.tv_sec;
1443 curpeers->peers_fe->id = strdup(args[1]);
1444 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001445 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001446 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1447 curpeers->peers_fe->timeout.connect = 5000;
1448 curpeers->peers_fe->accept = peer_accept;
1449 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001450
1451 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1452
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001453 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1454 if (err_msg && *err_msg) {
1455 indent_msg(&err_msg, 2);
1456 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1457 }
1458 else
1459 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1460 file, linenum, args[0], args[1], args[2]);
1461 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001462 err_code |= ERR_FATAL;
1463 goto out;
1464 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001465
1466 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1467 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1468 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1469 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1470 l->accept = session_accept;
1471 l->handler = process_session;
1472 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1473 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1474 global.maxsock += l->maxconn;
1475 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001476 }
1477 }
1478 } /* neither "peer" nor "peers" */
1479 else if (*args[0] != 0) {
1480 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485out:
1486 return err_code;
1487}
1488
1489
Willy Tarreau3842f002009-06-14 11:39:52 +02001490int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491{
1492 static struct proxy *curproxy = NULL;
1493 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001494 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001495 int rc;
1496 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001497 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001498 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001499 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001500 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001501 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 if (!strcmp(args[0], "listen"))
1504 rc = PR_CAP_LISTEN;
1505 else if (!strcmp(args[0], "frontend"))
1506 rc = PR_CAP_FE | PR_CAP_RS;
1507 else if (!strcmp(args[0], "backend"))
1508 rc = PR_CAP_BE | PR_CAP_RS;
1509 else if (!strcmp(args[0], "ruleset"))
1510 rc = PR_CAP_RS;
1511 else
1512 rc = PR_CAP_NONE;
1513
1514 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 if (!*args[1]) {
1516 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1517 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1518 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001519 err_code |= ERR_ALERT | ERR_ABORT;
1520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001521 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001522
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001523 err = invalid_char(args[1]);
1524 if (err) {
1525 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1526 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001527 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001528 }
1529
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001530 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1531 /*
1532 * If there are two proxies with the same name only following
1533 * combinations are allowed:
1534 *
1535 * listen backend frontend ruleset
1536 * listen - - - -
1537 * backend - - OK -
1538 * frontend - OK - -
1539 * ruleset - - - -
1540 */
1541
1542 if (!strcmp(curproxy->id, args[1]) &&
1543 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1544 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001545 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1546 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1547 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001548 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001549 }
1550 }
1551
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1553 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001554 err_code |= ERR_ALERT | ERR_ABORT;
1555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001557
Willy Tarreau97cb7802010-01-03 20:23:58 +01001558 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 curproxy->next = proxy;
1560 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001561 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001562 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001563 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001565 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566
1567 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001569 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001570 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001571
Willy Tarreau4348fad2012-09-20 16:48:07 +02001572 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1573
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001574 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1575 if (err_msg && *err_msg) {
1576 indent_msg(&err_msg, 2);
1577 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1578 }
1579 else
1580 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1581 file, linenum, args[0], args[1], args[2]);
1582 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_FATAL;
1584 goto out;
1585 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001586
Willy Tarreau4348fad2012-09-20 16:48:07 +02001587 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001588 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
1591
1592 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001593 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001594 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001595
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001598 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001599 curproxy->no_options = defproxy.no_options;
1600 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001601 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001602 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001603 curproxy->except_net = defproxy.except_net;
1604 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001605 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001606 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001608 if (defproxy.fwdfor_hdr_len) {
1609 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1610 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1611 }
1612
Willy Tarreaub86db342009-11-30 11:50:16 +01001613 if (defproxy.orgto_hdr_len) {
1614 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1615 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1616 }
1617
Mark Lamourinec2247f02012-01-04 13:02:01 -05001618 if (defproxy.server_id_hdr_len) {
1619 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1620 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1621 }
1622
Willy Tarreau977b8e42006-12-29 14:19:17 +01001623 if (curproxy->cap & PR_CAP_FE) {
1624 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001625 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001626 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627
1628 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001629 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1630 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631
1632 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634
Willy Tarreau977b8e42006-12-29 14:19:17 +01001635 if (curproxy->cap & PR_CAP_BE) {
1636 curproxy->fullconn = defproxy.fullconn;
1637 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001639 if (defproxy.check_req) {
1640 curproxy->check_req = calloc(1, defproxy.check_len);
1641 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1642 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001643 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001645 if (defproxy.expect_str) {
1646 curproxy->expect_str = strdup(defproxy.expect_str);
1647 if (defproxy.expect_regex) {
1648 /* note: this regex is known to be valid */
1649 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1650 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1651 }
1652 }
1653
Willy Tarreau67402132012-05-31 20:40:20 +02001654 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001655 if (defproxy.cookie_name)
1656 curproxy->cookie_name = strdup(defproxy.cookie_name);
1657 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001658 if (defproxy.cookie_domain)
1659 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001660
Willy Tarreau31936852010-10-06 16:59:56 +02001661 if (defproxy.cookie_maxidle)
1662 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1663
1664 if (defproxy.cookie_maxlife)
1665 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1666
Emeric Brun647caf12009-06-30 17:57:00 +02001667 if (defproxy.rdp_cookie_name)
1668 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1669 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1670
Willy Tarreau01732802007-11-01 22:48:15 +01001671 if (defproxy.url_param_name)
1672 curproxy->url_param_name = strdup(defproxy.url_param_name);
1673 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001674
Benoitaffb4812009-03-25 13:02:10 +01001675 if (defproxy.hh_name)
1676 curproxy->hh_name = strdup(defproxy.hh_name);
1677 curproxy->hh_len = defproxy.hh_len;
1678 curproxy->hh_match_domain = defproxy.hh_match_domain;
1679
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001680 if (defproxy.iface_name)
1681 curproxy->iface_name = strdup(defproxy.iface_name);
1682 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001685 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001686 if (defproxy.capture_name)
1687 curproxy->capture_name = strdup(defproxy.capture_name);
1688 curproxy->capture_namelen = defproxy.capture_namelen;
1689 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691
Willy Tarreau977b8e42006-12-29 14:19:17 +01001692 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001693 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001694 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001695 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001696 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001697 curproxy->uri_auth = defproxy.uri_auth;
1698 curproxy->mon_net = defproxy.mon_net;
1699 curproxy->mon_mask = defproxy.mon_mask;
1700 if (defproxy.monitor_uri)
1701 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1702 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001703 if (defproxy.defbe.name)
1704 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001705
1706 /* get either a pointer to the logformat string or a copy of it */
1707 curproxy->logformat_string = defproxy.logformat_string;
1708 if (curproxy->logformat_string &&
1709 curproxy->logformat_string != default_http_log_format &&
1710 curproxy->logformat_string != default_tcp_log_format &&
1711 curproxy->logformat_string != clf_http_log_format)
1712 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001713 }
1714
1715 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001716 curproxy->timeout.connect = defproxy.timeout.connect;
1717 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001718 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001719 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001720 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001721 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001722 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001723 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001724 curproxy->source_addr = defproxy.source_addr;
1725 }
1726
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001728
1729 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001730 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001731 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001732 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001733 LIST_INIT(&node->list);
1734 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1735 }
1736
Willy Tarreau196729e2012-05-31 19:30:26 +02001737 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1738 if (curproxy->uniqueid_format_string)
1739 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001740
1741 /* copy default header unique id */
1742 if (defproxy.header_unique_id)
1743 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1744
William Lallemand82fe75c2012-10-23 10:25:10 +02001745 /* default compression options */
1746 if (defproxy.comp != NULL) {
1747 curproxy->comp = calloc(1, sizeof(struct comp));
1748 curproxy->comp->algos = defproxy.comp->algos;
1749 curproxy->comp->types = defproxy.comp->types;
1750 }
1751
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001753 curproxy->conf.used_listener_id = EB_ROOT;
1754 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001755
Willy Tarreau93893792009-07-23 13:19:11 +02001756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1759 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001760 /* FIXME-20070101: we should do this too at the end of the
1761 * config parsing to free all default values.
1762 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001763 free(defproxy.check_req);
1764 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001765 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001766 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001767 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001768 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001769 free(defproxy.capture_name);
1770 free(defproxy.monitor_uri);
1771 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001772 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001773 free(defproxy.fwdfor_hdr_name);
1774 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001775 free(defproxy.orgto_hdr_name);
1776 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001777 free(defproxy.server_id_hdr_name);
1778 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001779 free(defproxy.expect_str);
1780 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001781
Willy Tarreau39b06652012-06-01 10:58:06 +02001782 if (defproxy.logformat_string != default_http_log_format &&
1783 defproxy.logformat_string != default_tcp_log_format &&
1784 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001785 free(defproxy.logformat_string);
1786
1787 free(defproxy.uniqueid_format_string);
1788
Willy Tarreaua534fea2008-08-03 12:19:50 +02001789 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001790 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001791
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 /* we cannot free uri_auth because it might already be used */
1793 init_default_instance();
1794 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 }
1798 else if (curproxy == NULL) {
1799 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803
Willy Tarreau977b8e42006-12-29 14:19:17 +01001804
1805 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001807 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001808 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001809 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001810
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 if (curproxy == &defproxy) {
1812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001816 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818
Emeric Bruned760922010-10-22 17:59:25 +02001819 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001820 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001825
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001826 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001827 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001828
1829 /* NOTE: the following line might create several listeners if there
1830 * are comma-separated IPs or port ranges. So all further processing
1831 * will have to be applied to all listeners created after last_listen.
1832 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001833 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1834 if (err_msg && *err_msg) {
1835 indent_msg(&err_msg, 2);
1836 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1837 }
1838 else
1839 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1840 file, linenum, args[0], args[1]);
1841 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001845
Willy Tarreau4348fad2012-09-20 16:48:07 +02001846 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1847 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001848 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001849 }
1850
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001851 cur_arg = 2;
1852 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001853 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001854 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001855 char *err;
1856
Willy Tarreau26982662012-09-12 23:17:10 +02001857 kw = bind_find_kw(args[cur_arg]);
1858 if (kw) {
1859 char *err = NULL;
1860 int code;
1861
1862 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001863 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1864 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001865 cur_arg += 1 + kw->skip ;
1866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
1868 }
1869
Willy Tarreau4348fad2012-09-20 16:48:07 +02001870 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001871 err_code |= code;
1872
1873 if (code) {
1874 if (err && *err) {
1875 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001876 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001877 }
1878 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001879 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1880 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001881 if (code & ERR_FATAL) {
1882 free(err);
1883 cur_arg += 1 + kw->skip;
1884 goto out;
1885 }
1886 }
1887 free(err);
1888 cur_arg += 1 + kw->skip;
1889 continue;
1890 }
1891
Willy Tarreau8638f482012-09-18 18:01:17 +02001892 err = NULL;
1893 if (!bind_dumped) {
1894 bind_dump_kws(&err);
1895 indent_msg(&err, 4);
1896 bind_dumped = 1;
1897 }
1898
1899 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1900 file, linenum, args[0], args[1], args[cur_arg],
1901 err ? " Registered keywords :" : "", err ? err : "");
1902 free(err);
1903
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001906 }
Willy Tarreau93893792009-07-23 13:19:11 +02001907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1910 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1911 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 /* flush useless bits */
1920 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001923 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001924 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001926
Willy Tarreau1c47f852006-07-09 08:22:27 +02001927 if (!*args[1]) {
1928 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 }
1933
Willy Tarreaua534fea2008-08-03 12:19:50 +02001934 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001935 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001936 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001937 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001938 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1939
Willy Tarreau93893792009-07-23 13:19:11 +02001940 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1943 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1944 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1945 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1946 else {
1947 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 }
1951 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001952 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954
1955 if (curproxy == &defproxy) {
1956 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001960 }
1961
1962 if (!*args[1]) {
1963 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1964 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001965 err_code |= ERR_ALERT | ERR_FATAL;
1966 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001967 }
1968
1969 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001970 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001971
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001972 if (curproxy->uuid <= 0) {
1973 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001974 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001975 err_code |= ERR_ALERT | ERR_FATAL;
1976 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001977 }
1978
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001979 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1980 if (node) {
1981 struct proxy *target = container_of(node, struct proxy, conf.id);
1982 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1983 file, linenum, proxy_type_str(curproxy), curproxy->id,
1984 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1985 err_code |= ERR_ALERT | ERR_FATAL;
1986 goto out;
1987 }
1988 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001989 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001990 else if (!strcmp(args[0], "description")) {
1991 int i, len=0;
1992 char *d;
1993
Cyril Bonté99ed3272010-01-24 23:29:44 +01001994 if (curproxy == &defproxy) {
1995 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1996 file, linenum, args[0]);
1997 err_code |= ERR_ALERT | ERR_FATAL;
1998 goto out;
1999 }
2000
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002001 if (!*args[1]) {
2002 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2003 file, linenum, args[0]);
2004 return -1;
2005 }
2006
2007 for(i=1; *args[i]; i++)
2008 len += strlen(args[i])+1;
2009
2010 d = (char *)calloc(1, len);
2011 curproxy->desc = d;
2012
2013 d += sprintf(d, "%s", args[1]);
2014 for(i=2; *args[i]; i++)
2015 d += sprintf(d, " %s", args[i]);
2016
2017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2019 curproxy->state = PR_STSTOPPED;
2020 }
2021 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2022 curproxy->state = PR_STNEW;
2023 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002024 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2025 int cur_arg = 1;
2026 unsigned int set = 0;
2027
2028 while (*args[cur_arg]) {
2029 int u;
2030 if (strcmp(args[cur_arg], "all") == 0) {
2031 set = 0;
2032 break;
2033 }
2034 else if (strcmp(args[cur_arg], "odd") == 0) {
2035 set |= 0x55555555;
2036 }
2037 else if (strcmp(args[cur_arg], "even") == 0) {
2038 set |= 0xAAAAAAAA;
2039 }
2040 else {
2041 u = str2uic(args[cur_arg]);
2042 if (u < 1 || u > 32) {
2043 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002047 }
2048 if (u > global.nbproc) {
2049 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002052 }
2053 set |= 1 << (u - 1);
2054 }
2055 cur_arg++;
2056 }
2057 curproxy->bind_proc = set;
2058 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002059 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002060 if (curproxy == &defproxy) {
2061 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002062 err_code |= ERR_ALERT | ERR_FATAL;
2063 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002064 }
2065
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002066 err = invalid_char(args[1]);
2067 if (err) {
2068 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2069 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002071 }
2072
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002073 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2074 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2075 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002078 }
2079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2081 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082
Willy Tarreau977b8e42006-12-29 14:19:17 +01002083 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002084 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002085
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086 if (*(args[1]) == 0) {
2087 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2088 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002091 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002092
Willy Tarreau67402132012-05-31 20:40:20 +02002093 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002094 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002095 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002096 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 curproxy->cookie_name = strdup(args[1]);
2098 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002099
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 cur_arg = 2;
2101 while (*(args[cur_arg])) {
2102 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002103 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
2105 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002106 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 }
2108 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002109 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 }
2111 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002112 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 }
2114 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002115 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002117 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002118 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002121 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002123 else if (!strcmp(args[cur_arg], "httponly")) {
2124 curproxy->ck_opts |= PR_CK_HTTPONLY;
2125 }
2126 else if (!strcmp(args[cur_arg], "secure")) {
2127 curproxy->ck_opts |= PR_CK_SECURE;
2128 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 else if (!strcmp(args[cur_arg], "domain")) {
2130 if (!*args[cur_arg + 1]) {
2131 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2132 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002135 }
2136
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002137 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002138 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002139 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2140 " dots nor does not start with a dot."
2141 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002143 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002144 }
2145
2146 err = invalid_domainchar(args[cur_arg + 1]);
2147 if (err) {
2148 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2149 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002152 }
2153
Willy Tarreau68a897b2009-12-03 23:28:34 +01002154 if (!curproxy->cookie_domain) {
2155 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2156 } else {
2157 /* one domain was already specified, add another one by
2158 * building the string which will be returned along with
2159 * the cookie.
2160 */
2161 char *new_ptr;
2162 int new_len = strlen(curproxy->cookie_domain) +
2163 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2164 new_ptr = malloc(new_len);
2165 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2166 free(curproxy->cookie_domain);
2167 curproxy->cookie_domain = new_ptr;
2168 }
Willy Tarreau31936852010-10-06 16:59:56 +02002169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxidle")) {
2172 unsigned int maxidle;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2177 file, linenum, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2183 if (res) {
2184 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2185 file, linenum, *res, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189 curproxy->cookie_maxidle = maxidle;
2190 cur_arg++;
2191 }
2192 else if (!strcmp(args[cur_arg], "maxlife")) {
2193 unsigned int maxlife;
2194 const char *res;
2195
2196 if (!*args[cur_arg + 1]) {
2197 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2198 file, linenum, args[cur_arg]);
2199 err_code |= ERR_ALERT | ERR_FATAL;
2200 goto out;
2201 }
2202
2203 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2204 if (res) {
2205 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2206 file, linenum, *res, args[cur_arg]);
2207 err_code |= ERR_ALERT | ERR_FATAL;
2208 goto out;
2209 }
2210 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002211 cur_arg++;
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002214 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 +02002215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_ALERT | ERR_FATAL;
2217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
2219 cur_arg++;
2220 }
Willy Tarreau67402132012-05-31 20:40:20 +02002221 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2223 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225 }
2226
Willy Tarreau67402132012-05-31 20:40:20 +02002227 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2229 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002232
Willy Tarreau67402132012-05-31 20:40:20 +02002233 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002234 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2235 file, linenum);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002239 else if (!strcmp(args[0], "persist")) { /* persist */
2240 if (*(args[1]) == 0) {
2241 Alert("parsing [%s:%d] : missing persist method.\n",
2242 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002245 }
2246
2247 if (!strncmp(args[1], "rdp-cookie", 10)) {
2248 curproxy->options2 |= PR_O2_RDPC_PRST;
2249
Emeric Brunb982a3d2010-01-04 15:45:53 +01002250 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002251 const char *beg, *end;
2252
2253 beg = args[1] + 11;
2254 end = strchr(beg, ')');
2255
2256 if (!end || end == beg) {
2257 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262
2263 free(curproxy->rdp_cookie_name);
2264 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2265 curproxy->rdp_cookie_len = end-beg;
2266 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002267 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002268 free(curproxy->rdp_cookie_name);
2269 curproxy->rdp_cookie_name = strdup("msts");
2270 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2271 }
2272 else { /* syntax */
2273 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002277 }
2278 }
2279 else {
2280 Alert("parsing [%s:%d] : unknown persist method.\n",
2281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002284 }
2285 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002287 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002289 if (curproxy == &defproxy) {
2290 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
2293 }
2294
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002297
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002299 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 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 }
2304 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002305 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 curproxy->appsession_name = strdup(args[1]);
2307 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2308 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002309 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2310 if (err) {
2311 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2312 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002315 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002316 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002317
Willy Tarreau51041c72007-09-09 21:56:53 +02002318 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2319 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002320 err_code |= ERR_ALERT | ERR_ABORT;
2321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002323
2324 cur_arg = 6;
2325 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002326 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2327 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002331 } else if (!strcmp(args[cur_arg], "prefix")) {
2332 curproxy->options2 |= PR_O2_AS_PFX;
2333 } else if (!strcmp(args[cur_arg], "mode")) {
2334 if (!*args[cur_arg + 1]) {
2335 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2336 file, linenum, args[0], args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 cur_arg++;
2342 if (!strcmp(args[cur_arg], "query-string")) {
2343 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2344 curproxy->options2 |= PR_O2_AS_M_QS;
2345 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2346 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2347 curproxy->options2 |= PR_O2_AS_M_PP;
2348 } else {
2349 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
2352 }
2353 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002354 cur_arg++;
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 } /* Url App Session */
2357 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002358 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002360
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002362 if (curproxy == &defproxy) {
2363 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
2366 }
2367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[4]) == 0) {
2369 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002374 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 curproxy->capture_name = strdup(args[2]);
2376 curproxy->capture_namelen = strlen(curproxy->capture_name);
2377 curproxy->capture_len = atol(args[4]);
2378 if (curproxy->capture_len >= CAPTURE_LEN) {
2379 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2380 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 curproxy->capture_len = CAPTURE_LEN - 1;
2383 }
2384 curproxy->to_log |= LW_COOKIE;
2385 }
2386 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2387 struct cap_hdr *hdr;
2388
2389 if (curproxy == &defproxy) {
2390 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 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394
2395 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2396 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2397 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401
2402 hdr = calloc(sizeof(struct cap_hdr), 1);
2403 hdr->next = curproxy->req_cap;
2404 hdr->name = strdup(args[3]);
2405 hdr->namelen = strlen(args[3]);
2406 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002407 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 hdr->index = curproxy->nb_req_cap++;
2409 curproxy->req_cap = hdr;
2410 curproxy->to_log |= LW_REQHDR;
2411 }
2412 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2413 struct cap_hdr *hdr;
2414
2415 if (curproxy == &defproxy) {
2416 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 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420
2421 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2422 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
2427 hdr = calloc(sizeof(struct cap_hdr), 1);
2428 hdr->next = curproxy->rsp_cap;
2429 hdr->name = strdup(args[3]);
2430 hdr->namelen = strlen(args[3]);
2431 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002432 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 hdr->index = curproxy->nb_rsp_cap++;
2434 curproxy->rsp_cap = hdr;
2435 curproxy->to_log |= LW_RSPHDR;
2436 }
2437 else {
2438 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002446 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002447
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 if (*(args[1]) == 0) {
2449 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 curproxy->conn_retries = atol(args[1]);
2455 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002457 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002458
2459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
Willy Tarreauff011f22011-01-06 17:51:27 +01002465 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 +01002466 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2467 file, linenum, args[0]);
2468 err_code |= ERR_WARN;
2469 }
2470
Willy Tarreauff011f22011-01-06 17:51:27 +01002471 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002472
Willy Tarreauff011f22011-01-06 17:51:27 +01002473 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002474 err_code |= ERR_ALERT | ERR_ABORT;
2475 goto out;
2476 }
2477
Willy Tarreauff011f22011-01-06 17:51:27 +01002478 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2479 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002480 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002481 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2482 /* set the header name and length into the proxy structure */
2483 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2484 err_code |= ERR_WARN;
2485
2486 if (!*args[1]) {
2487 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2488 file, linenum, args[0]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493 /* set the desired header name */
2494 free(curproxy->server_id_hdr_name);
2495 curproxy->server_id_hdr_name = strdup(args[1]);
2496 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2497 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002498 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002499 if (curproxy == &defproxy) {
2500 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002503 }
2504
Willy Tarreauef6494c2010-01-28 17:12:36 +01002505 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002506 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2507 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002510 }
2511
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002512 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2513 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2514 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002517 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002518
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002519 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002520 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002521 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002523 struct redirect_rule *rule;
2524 int cur_arg;
2525 int type = REDIRECT_TYPE_NONE;
2526 int code = 302;
2527 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002528 char *cookie = NULL;
2529 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002530 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002531
Cyril Bonté99ed3272010-01-24 23:29:44 +01002532 if (curproxy == &defproxy) {
2533 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
2536 }
2537
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002538 cur_arg = 1;
2539 while (*(args[cur_arg])) {
2540 if (!strcmp(args[cur_arg], "location")) {
2541 if (!*args[cur_arg + 1]) {
2542 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2543 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002546 }
2547
2548 type = REDIRECT_TYPE_LOCATION;
2549 cur_arg++;
2550 destination = args[cur_arg];
2551 }
2552 else if (!strcmp(args[cur_arg], "prefix")) {
2553 if (!*args[cur_arg + 1]) {
2554 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2555 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002558 }
2559
2560 type = REDIRECT_TYPE_PREFIX;
2561 cur_arg++;
2562 destination = args[cur_arg];
2563 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002564 else if (!strcmp(args[cur_arg], "scheme")) {
2565 if (!*args[cur_arg + 1]) {
2566 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2567 file, linenum, args[0], args[cur_arg]);
2568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
2570 }
2571
2572 type = REDIRECT_TYPE_SCHEME;
2573 cur_arg++;
2574 destination = args[cur_arg];
2575 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002576 else if (!strcmp(args[cur_arg], "set-cookie")) {
2577 if (!*args[cur_arg + 1]) {
2578 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2579 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002582 }
2583
2584 cur_arg++;
2585 cookie = args[cur_arg];
2586 cookie_set = 1;
2587 }
2588 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2589 if (!*args[cur_arg + 1]) {
2590 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2591 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 }
2595
2596 cur_arg++;
2597 cookie = args[cur_arg];
2598 cookie_set = 0;
2599 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 else if (!strcmp(args[cur_arg],"code")) {
2601 if (!*args[cur_arg + 1]) {
2602 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002606 }
2607 cur_arg++;
2608 code = atol(args[cur_arg]);
2609 if (code < 301 || code > 303) {
2610 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2611 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002614 }
2615 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002616 else if (!strcmp(args[cur_arg],"drop-query")) {
2617 flags |= REDIRECT_FLAG_DROP_QS;
2618 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002619 else if (!strcmp(args[cur_arg],"append-slash")) {
2620 flags |= REDIRECT_FLAG_APPEND_SLASH;
2621 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002622 else if (strcmp(args[cur_arg], "if") == 0 ||
2623 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002624 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002625 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002626 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2627 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
2630 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002631 break;
2632 }
2633 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002634 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 +02002635 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002638 }
2639 cur_arg++;
2640 }
2641
2642 if (type == REDIRECT_TYPE_NONE) {
2643 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002647 }
2648
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2650 rule->cond = cond;
2651 rule->rdr_str = strdup(destination);
2652 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002653 if (cookie) {
2654 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002655 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002656 */
2657 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002658 if (cookie_set) {
2659 rule->cookie_str = malloc(rule->cookie_len + 10);
2660 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2661 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2662 rule->cookie_len += 9;
2663 } else {
2664 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002665 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002666 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2667 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002668 }
2669 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002670 rule->type = type;
2671 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002672 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002673 LIST_INIT(&rule->list);
2674 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002675 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2676 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002677 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002678 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002679 struct switching_rule *rule;
2680
Willy Tarreaub099aca2008-10-12 17:26:37 +02002681 if (curproxy == &defproxy) {
2682 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002685 }
2686
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689
2690 if (*(args[1]) == 0) {
2691 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002694 }
2695
Willy Tarreauef6494c2010-01-28 17:12:36 +01002696 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002697 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002701 }
2702
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002703 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2704 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2705 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
2707 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002708 }
2709
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002710 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002711
Willy Tarreau55ea7572007-06-17 19:56:27 +02002712 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2713 rule->cond = cond;
2714 rule->be.name = strdup(args[1]);
2715 LIST_INIT(&rule->list);
2716 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2717 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002718 else if (strcmp(args[0], "use-server") == 0) {
2719 struct server_rule *rule;
2720
2721 if (curproxy == &defproxy) {
2722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726
2727 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2728 err_code |= ERR_WARN;
2729
2730 if (*(args[1]) == 0) {
2731 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735
2736 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2737 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2738 file, linenum, args[0]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
2742
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002743 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2744 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2745 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749
2750 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2751
2752 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2753 rule->cond = cond;
2754 rule->srv.name = strdup(args[1]);
2755 LIST_INIT(&rule->list);
2756 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2757 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2758 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002759 else if ((!strcmp(args[0], "force-persist")) ||
2760 (!strcmp(args[0], "ignore-persist"))) {
2761 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002762
2763 if (curproxy == &defproxy) {
2764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768
2769 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2770 err_code |= ERR_WARN;
2771
Willy Tarreauef6494c2010-01-28 17:12:36 +01002772 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002773 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2774 file, linenum, args[0]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002779 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2780 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2781 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002786 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002787
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002788 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002789 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002790 if (!strcmp(args[0], "force-persist")) {
2791 rule->type = PERSIST_TYPE_FORCE;
2792 } else {
2793 rule->type = PERSIST_TYPE_IGNORE;
2794 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002795 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002796 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002797 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002798 else if (!strcmp(args[0], "stick-table")) {
2799 int myidx = 1;
2800
Emeric Brun32da3c42010-09-23 18:39:19 +02002801 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002802 curproxy->table.type = (unsigned int)-1;
2803 while (*args[myidx]) {
2804 const char *err;
2805
2806 if (strcmp(args[myidx], "size") == 0) {
2807 myidx++;
2808 if (!*(args[myidx])) {
2809 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2810 file, linenum, args[myidx-1]);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2815 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2816 file, linenum, *err, args[myidx-1]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002820 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002821 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002822 else if (strcmp(args[myidx], "peers") == 0) {
2823 myidx++;
2824 if (!*(args[myidx])) {
2825 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2826 file, linenum, args[myidx-1]);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830 curproxy->table.peers.name = strdup(args[myidx++]);
2831 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 else if (strcmp(args[myidx], "expire") == 0) {
2833 myidx++;
2834 if (!*(args[myidx])) {
2835 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2836 file, linenum, args[myidx-1]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2841 if (err) {
2842 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2843 file, linenum, *err, args[myidx-1]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
2846 }
2847 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002848 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002849 }
2850 else if (strcmp(args[myidx], "nopurge") == 0) {
2851 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002852 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002853 }
2854 else if (strcmp(args[myidx], "type") == 0) {
2855 myidx++;
2856 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2857 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2858 file, linenum, args[myidx]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002862 /* myidx already points to next arg */
2863 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002864 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002865 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002866 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002867
2868 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002869 nw = args[myidx];
2870 while (*nw) {
2871 /* the "store" keyword supports a comma-separated list */
2872 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002873 sa = NULL; /* store arg */
2874 while (*nw && *nw != ',') {
2875 if (*nw == '(') {
2876 *nw = 0;
2877 sa = ++nw;
2878 while (*nw != ')') {
2879 if (!*nw) {
2880 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2881 file, linenum, args[0], cw);
2882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885 nw++;
2886 }
2887 *nw = '\0';
2888 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002889 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002890 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002891 if (*nw)
2892 *nw++ = '\0';
2893 type = stktable_get_data_type(cw);
2894 if (type < 0) {
2895 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2896 file, linenum, args[0], cw);
2897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
2899 }
Willy Tarreauac782882010-06-20 10:41:54 +02002900
2901 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2902 switch (err) {
2903 case PE_NONE: break;
2904 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002905 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2906 file, linenum, args[0], cw);
2907 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002908 break;
2909
2910 case PE_ARG_MISSING:
2911 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915
2916 case PE_ARG_NOT_USED:
2917 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2918 file, linenum, args[0], cw);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921
2922 default:
2923 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2924 file, linenum, args[0], cw);
2925 err_code |= ERR_ALERT | ERR_FATAL;
2926 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002927 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002928 }
2929 myidx++;
2930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002931 else {
2932 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2933 file, linenum, args[myidx]);
2934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 }
2938
2939 if (!curproxy->table.size) {
2940 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2941 file, linenum);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (curproxy->table.type == (unsigned int)-1) {
2947 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2948 file, linenum);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 }
2953 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002954 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002955 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 int myidx = 0;
2957 const char *name = NULL;
2958 int flags;
2959
2960 if (curproxy == &defproxy) {
2961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965
2966 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2967 err_code |= ERR_WARN;
2968 goto out;
2969 }
2970
2971 myidx++;
2972 if ((strcmp(args[myidx], "store") == 0) ||
2973 (strcmp(args[myidx], "store-request") == 0)) {
2974 myidx++;
2975 flags = STK_IS_STORE;
2976 }
2977 else if (strcmp(args[myidx], "store-response") == 0) {
2978 myidx++;
2979 flags = STK_IS_STORE | STK_ON_RSP;
2980 }
2981 else if (strcmp(args[myidx], "match") == 0) {
2982 myidx++;
2983 flags = STK_IS_MATCH;
2984 }
2985 else if (strcmp(args[myidx], "on") == 0) {
2986 myidx++;
2987 flags = STK_IS_MATCH | STK_IS_STORE;
2988 }
2989 else {
2990 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 if (*(args[myidx]) == 0) {
2996 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
2999 }
3000
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003001 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003002 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003003 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 err_code |= ERR_ALERT | ERR_FATAL;
3005 goto out;
3006 }
3007
3008 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003009 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3011 file, linenum, args[0], expr->fetch->kw);
3012 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003013 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 goto out;
3015 }
3016 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003017 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003018 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3019 file, linenum, args[0], expr->fetch->kw);
3020 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003021 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 goto out;
3023 }
3024 }
3025
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003026 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3027 if (expr->fetch->cap & SMP_CAP_L7)
3028 curproxy->acl_requires |= ACL_USE_L7_ANY;
3029
Emeric Brunb982a3d2010-01-04 15:45:53 +01003030 if (strcmp(args[myidx], "table") == 0) {
3031 myidx++;
3032 name = args[myidx++];
3033 }
3034
Willy Tarreauef6494c2010-01-28 17:12:36 +01003035 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003036 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3037 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3038 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003040 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 goto out;
3042 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003044 else if (*(args[myidx])) {
3045 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3046 file, linenum, args[0], args[myidx]);
3047 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003048 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003049 goto out;
3050 }
Emeric Brun97679e72010-09-23 17:56:44 +02003051 if (flags & STK_ON_RSP)
3052 err_code |= warnif_cond_requires_req(cond, file, linenum);
3053 else
3054 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003055
Emeric Brunb982a3d2010-01-04 15:45:53 +01003056 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3057 rule->cond = cond;
3058 rule->expr = expr;
3059 rule->flags = flags;
3060 rule->table.name = name ? strdup(name) : NULL;
3061 LIST_INIT(&rule->list);
3062 if (flags & STK_ON_RSP)
3063 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3064 else
3065 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003070
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3072 curproxy->uri_auth = NULL; /* we must detach from the default config */
3073
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003074 if (!*args[1]) {
3075 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003076 } else if (!strcmp(args[1], "admin")) {
3077 struct stats_admin_rule *rule;
3078
3079 if (curproxy == &defproxy) {
3080 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
3085 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3086 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
3089 }
3090
3091 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3092 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3093 file, linenum, args[0], args[1]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003097 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3098 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3099 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103
3104 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3105
3106 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3107 rule->cond = cond;
3108 LIST_INIT(&rule->list);
3109 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 } else if (!strcmp(args[1], "uri")) {
3111 if (*(args[2]) == 0) {
3112 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3116 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003117 err_code |= ERR_ALERT | ERR_ABORT;
3118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
3120 } else if (!strcmp(args[1], "realm")) {
3121 if (*(args[2]) == 0) {
3122 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_ABORT;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003130 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003131 unsigned interval;
3132
3133 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3134 if (err) {
3135 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3136 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003139 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3140 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003143 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003144 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003145 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146
3147 if (curproxy == &defproxy) {
3148 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152
3153 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3154 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3155 err_code |= ERR_ALERT | ERR_ABORT;
3156 goto out;
3157 }
3158
Willy Tarreauff011f22011-01-06 17:51:27 +01003159 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3160 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003161 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3162 file, linenum, args[0]);
3163 err_code |= ERR_WARN;
3164 }
3165
Willy Tarreauff011f22011-01-06 17:51:27 +01003166 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003167
Willy Tarreauff011f22011-01-06 17:51:27 +01003168 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003169 err_code |= ERR_ALERT | ERR_ABORT;
3170 goto out;
3171 }
3172
Willy Tarreauff011f22011-01-06 17:51:27 +01003173 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3174 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003175
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 } else if (!strcmp(args[1], "auth")) {
3177 if (*(args[2]) == 0) {
3178 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3182 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_ALERT | ERR_ABORT;
3184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 }
3186 } else if (!strcmp(args[1], "scope")) {
3187 if (*(args[2]) == 0) {
3188 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_ALERT | ERR_ABORT;
3194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 }
3196 } else if (!strcmp(args[1], "enable")) {
3197 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_ABORT;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003202 } else if (!strcmp(args[1], "hide-version")) {
3203 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_ABORT;
3206 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003207 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003208 } else if (!strcmp(args[1], "show-legends")) {
3209 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3210 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3211 err_code |= ERR_ALERT | ERR_ABORT;
3212 goto out;
3213 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003214 } else if (!strcmp(args[1], "show-node")) {
3215
3216 if (*args[2]) {
3217 int i;
3218 char c;
3219
3220 for (i=0; args[2][i]; i++) {
3221 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003222 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3223 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003224 break;
3225 }
3226
3227 if (!i || args[2][i]) {
3228 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3229 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3230 file, linenum, args[0], args[1]);
3231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
3233 }
3234 }
3235
3236 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3238 err_code |= ERR_ALERT | ERR_ABORT;
3239 goto out;
3240 }
3241 } else if (!strcmp(args[1], "show-desc")) {
3242 char *desc = NULL;
3243
3244 if (*args[2]) {
3245 int i, len=0;
3246 char *d;
3247
3248 for(i=2; *args[i]; i++)
3249 len += strlen(args[i])+1;
3250
3251 desc = d = (char *)calloc(1, len);
3252
3253 d += sprintf(d, "%s", args[2]);
3254 for(i=3; *args[i]; i++)
3255 d += sprintf(d, " %s", args[i]);
3256 }
3257
3258 if (!*args[2] && !global.desc)
3259 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3260 file, linenum, args[1]);
3261 else {
3262 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3263 free(desc);
3264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268 free(desc);
3269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003271stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003272 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 +01003273 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_FATAL;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 }
3278 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003279 int optnum;
3280
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003281 if (*(args[1]) == '\0') {
3282 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3283 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003287
3288 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3289 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003290 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3291 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3292 file, linenum, cfg_opts[optnum].name);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
Willy Tarreau93893792009-07-23 13:19:11 +02003296 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3297 err_code |= ERR_WARN;
3298 goto out;
3299 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003300
Willy Tarreau3842f002009-06-14 11:39:52 +02003301 curproxy->no_options &= ~cfg_opts[optnum].val;
3302 curproxy->options &= ~cfg_opts[optnum].val;
3303
3304 switch (kwm) {
3305 case KWM_STD:
3306 curproxy->options |= cfg_opts[optnum].val;
3307 break;
3308 case KWM_NO:
3309 curproxy->no_options |= cfg_opts[optnum].val;
3310 break;
3311 case KWM_DEF: /* already cleared */
3312 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003313 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003314
Willy Tarreau93893792009-07-23 13:19:11 +02003315 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003316 }
3317 }
3318
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003319 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3320 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003321 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3322 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3323 file, linenum, cfg_opts2[optnum].name);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326 }
Willy Tarreau93893792009-07-23 13:19:11 +02003327 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3328 err_code |= ERR_WARN;
3329 goto out;
3330 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003331
Willy Tarreau3842f002009-06-14 11:39:52 +02003332 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3333 curproxy->options2 &= ~cfg_opts2[optnum].val;
3334
3335 switch (kwm) {
3336 case KWM_STD:
3337 curproxy->options2 |= cfg_opts2[optnum].val;
3338 break;
3339 case KWM_NO:
3340 curproxy->no_options2 |= cfg_opts2[optnum].val;
3341 break;
3342 case KWM_DEF: /* already cleared */
3343 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003344 }
Willy Tarreau93893792009-07-23 13:19:11 +02003345 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003346 }
3347 }
3348
Willy Tarreau3842f002009-06-14 11:39:52 +02003349 if (kwm != KWM_STD) {
3350 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003351 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003354 }
3355
Emeric Brun3a058f32009-06-30 18:26:00 +02003356 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003357 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003359 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003360 if (*(args[2]) != '\0') {
3361 if (!strcmp(args[2], "clf")) {
3362 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003363 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003364 } else {
3365 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003368 }
3369 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003370 if (curproxy->logformat_string != default_http_log_format &&
3371 curproxy->logformat_string != default_tcp_log_format &&
3372 curproxy->logformat_string != clf_http_log_format)
3373 free(curproxy->logformat_string);
3374 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003375 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003376 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003378 if (curproxy->logformat_string != default_http_log_format &&
3379 curproxy->logformat_string != default_tcp_log_format &&
3380 curproxy->logformat_string != clf_http_log_format)
3381 free(curproxy->logformat_string);
3382 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 else if (!strcmp(args[1], "tcpka")) {
3385 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003386 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003388
3389 if (curproxy->cap & PR_CAP_FE)
3390 curproxy->options |= PR_O_TCP_CLI_KA;
3391 if (curproxy->cap & PR_CAP_BE)
3392 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003395 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_WARN;
3397
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003399 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003400 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003401 curproxy->options2 &= ~PR_O2_CHK_ANY;
3402 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 if (!*args[2]) { /* no argument */
3404 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3405 curproxy->check_len = strlen(DEF_CHECK_REQ);
3406 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003407 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 curproxy->check_req = (char *)malloc(reqlen);
3409 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003410 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003412 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 if (*args[4])
3414 reqlen += strlen(args[4]);
3415 else
3416 reqlen += strlen("HTTP/1.0");
3417
3418 curproxy->check_req = (char *)malloc(reqlen);
3419 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003420 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003422 }
3423 else if (!strcmp(args[1], "ssl-hello-chk")) {
3424 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003425 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003426 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003427
Willy Tarreaua534fea2008-08-03 12:19:50 +02003428 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003429 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003430 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003431 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 }
Willy Tarreau23677902007-05-08 23:50:35 +02003433 else if (!strcmp(args[1], "smtpchk")) {
3434 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003435 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003436 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003437 curproxy->options2 &= ~PR_O2_CHK_ANY;
3438 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003439
3440 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3441 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3442 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3443 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3444 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3445 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3446 curproxy->check_req = (char *)malloc(reqlen);
3447 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3448 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3449 } else {
3450 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3451 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3452 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3453 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3454 }
3455 }
3456 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003457 else if (!strcmp(args[1], "pgsql-check")) {
3458 /* use PostgreSQL request to check servers' health */
3459 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3460 err_code |= ERR_WARN;
3461
3462 free(curproxy->check_req);
3463 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003464 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003465 curproxy->options2 |= PR_O2_PGSQL_CHK;
3466
3467 if (*(args[2])) {
3468 int cur_arg = 2;
3469
3470 while (*(args[cur_arg])) {
3471 if (strcmp(args[cur_arg], "user") == 0) {
3472 char * packet;
3473 uint32_t packet_len;
3474 uint32_t pv;
3475
3476 /* suboption header - needs additional argument for it */
3477 if (*(args[cur_arg+1]) == 0) {
3478 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3479 file, linenum, args[0], args[1], args[cur_arg]);
3480 err_code |= ERR_ALERT | ERR_FATAL;
3481 goto out;
3482 }
3483
3484 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3485 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3486 pv = htonl(0x30000); /* protocol version 3.0 */
3487
3488 packet = (char*) calloc(1, packet_len);
3489
3490 memcpy(packet + 4, &pv, 4);
3491
3492 /* copy "user" */
3493 memcpy(packet + 8, "user", 4);
3494
3495 /* copy username */
3496 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3497
3498 free(curproxy->check_req);
3499 curproxy->check_req = packet;
3500 curproxy->check_len = packet_len;
3501
3502 packet_len = htonl(packet_len);
3503 memcpy(packet, &packet_len, 4);
3504 cur_arg += 2;
3505 } else {
3506 /* unknown suboption - catchall */
3507 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3508 file, linenum, args[0], args[1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512 } /* end while loop */
3513 }
3514 }
3515
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003516 else if (!strcmp(args[1], "redis-check")) {
3517 /* use REDIS PING request to check servers' health */
3518 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3519 err_code |= ERR_WARN;
3520
3521 free(curproxy->check_req);
3522 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003523 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003524 curproxy->options2 |= PR_O2_REDIS_CHK;
3525
3526 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3527 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3528 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3529 }
3530
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003531 else if (!strcmp(args[1], "mysql-check")) {
3532 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003533 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3534 err_code |= ERR_WARN;
3535
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003536 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003537 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003538 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003539 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003540
3541 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3542 * const char mysql40_client_auth_pkt[] = {
3543 * "\x0e\x00\x00" // packet length
3544 * "\x01" // packet number
3545 * "\x00\x00" // client capabilities
3546 * "\x00\x00\x01" // max packet
3547 * "haproxy\x00" // username (null terminated string)
3548 * "\x00" // filler (always 0x00)
3549 * "\x01\x00\x00" // packet length
3550 * "\x00" // packet number
3551 * "\x01" // COM_QUIT command
3552 * };
3553 */
3554
3555 if (*(args[2])) {
3556 int cur_arg = 2;
3557
3558 while (*(args[cur_arg])) {
3559 if (strcmp(args[cur_arg], "user") == 0) {
3560 char *mysqluser;
3561 int packetlen, reqlen, userlen;
3562
3563 /* suboption header - needs additional argument for it */
3564 if (*(args[cur_arg+1]) == 0) {
3565 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3566 file, linenum, args[0], args[1], args[cur_arg]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
3570 mysqluser = args[cur_arg + 1];
3571 userlen = strlen(mysqluser);
3572 packetlen = userlen + 7;
3573 reqlen = packetlen + 9;
3574
3575 free(curproxy->check_req);
3576 curproxy->check_req = (char *)calloc(1, reqlen);
3577 curproxy->check_len = reqlen;
3578
3579 snprintf(curproxy->check_req, 4, "%c%c%c",
3580 ((unsigned char) packetlen & 0xff),
3581 ((unsigned char) (packetlen >> 8) & 0xff),
3582 ((unsigned char) (packetlen >> 16) & 0xff));
3583
3584 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003585 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003586 curproxy->check_req[8] = 1;
3587 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3588 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3589 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3590 cur_arg += 2;
3591 } else {
3592 /* unknown suboption - catchall */
3593 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3594 file, linenum, args[0], args[1]);
3595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
3597 }
3598 } /* end while loop */
3599 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003600 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003601 else if (!strcmp(args[1], "ldap-check")) {
3602 /* use LDAP request to check servers' health */
3603 free(curproxy->check_req);
3604 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003605 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003606 curproxy->options2 |= PR_O2_LDAP_CHK;
3607
3608 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3609 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3610 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3611 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003612 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003613 int cur_arg;
3614
3615 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3616 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003617 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003618
Willy Tarreau87cf5142011-08-19 22:57:24 +02003619 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003620
3621 free(curproxy->fwdfor_hdr_name);
3622 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3623 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3624
3625 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3626 cur_arg = 2;
3627 while (*(args[cur_arg])) {
3628 if (!strcmp(args[cur_arg], "except")) {
3629 /* suboption except - needs additional argument for it */
3630 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3631 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3632 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003635 }
3636 /* flush useless bits */
3637 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003638 cur_arg += 2;
3639 } else if (!strcmp(args[cur_arg], "header")) {
3640 /* suboption header - needs additional argument for it */
3641 if (*(args[cur_arg+1]) == 0) {
3642 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3643 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_ALERT | ERR_FATAL;
3645 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003646 }
3647 free(curproxy->fwdfor_hdr_name);
3648 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3649 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3650 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003651 } else if (!strcmp(args[cur_arg], "if-none")) {
3652 curproxy->options &= ~PR_O_FF_ALWAYS;
3653 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003654 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003655 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003656 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003657 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003660 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003661 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003663 else if (!strcmp(args[1], "originalto")) {
3664 int cur_arg;
3665
3666 /* insert x-original-to field, but not for the IP address listed as an except.
3667 * set default options (ie: bitfield, header name, etc)
3668 */
3669
3670 curproxy->options |= PR_O_ORGTO;
3671
3672 free(curproxy->orgto_hdr_name);
3673 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3674 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3675
Willy Tarreau87cf5142011-08-19 22:57:24 +02003676 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003677 cur_arg = 2;
3678 while (*(args[cur_arg])) {
3679 if (!strcmp(args[cur_arg], "except")) {
3680 /* suboption except - needs additional argument for it */
3681 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3683 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003686 }
3687 /* flush useless bits */
3688 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3689 cur_arg += 2;
3690 } else if (!strcmp(args[cur_arg], "header")) {
3691 /* suboption header - needs additional argument for it */
3692 if (*(args[cur_arg+1]) == 0) {
3693 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3694 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003697 }
3698 free(curproxy->orgto_hdr_name);
3699 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3700 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3701 cur_arg += 2;
3702 } else {
3703 /* unknown suboption - catchall */
3704 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3705 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003708 }
3709 } /* end while loop */
3710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003711 else {
3712 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 }
Willy Tarreau93893792009-07-23 13:19:11 +02003716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003718 else if (!strcmp(args[0], "default_backend")) {
3719 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003720 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003721
3722 if (*(args[1]) == 0) {
3723 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003726 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003727 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003728 curproxy->defbe.name = strdup(args[1]);
3729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003730 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003733
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003734 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 /* enable reconnections to dispatch */
3738 curproxy->options |= PR_O_REDISP;
3739 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003740 else if (!strcmp(args[0], "http-check")) {
3741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003743
3744 if (strcmp(args[1], "disable-on-404") == 0) {
3745 /* enable a graceful server shutdown on an HTTP 404 response */
3746 curproxy->options |= PR_O_DISABLE404;
3747 }
Willy Tarreauef781042010-01-27 11:53:01 +01003748 else if (strcmp(args[1], "send-state") == 0) {
3749 /* enable emission of the apparent state of a server in HTTP checks */
3750 curproxy->options2 |= PR_O2_CHK_SNDST;
3751 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003752 else if (strcmp(args[1], "expect") == 0) {
3753 const char *ptr_arg;
3754 int cur_arg;
3755
3756 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3757 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
3760 }
3761
3762 cur_arg = 2;
3763 /* consider exclamation marks, sole or at the beginning of a word */
3764 while (*(ptr_arg = args[cur_arg])) {
3765 while (*ptr_arg == '!') {
3766 curproxy->options2 ^= PR_O2_EXP_INV;
3767 ptr_arg++;
3768 }
3769 if (*ptr_arg)
3770 break;
3771 cur_arg++;
3772 }
3773 /* now ptr_arg points to the beginning of a word past any possible
3774 * exclamation mark, and cur_arg is the argument which holds this word.
3775 */
3776 if (strcmp(ptr_arg, "status") == 0) {
3777 if (!*(args[cur_arg + 1])) {
3778 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3779 file, linenum, args[0], args[1], ptr_arg);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782 }
3783 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003784 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003785 curproxy->expect_str = strdup(args[cur_arg + 1]);
3786 }
3787 else if (strcmp(ptr_arg, "string") == 0) {
3788 if (!*(args[cur_arg + 1])) {
3789 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3790 file, linenum, args[0], args[1], ptr_arg);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003795 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003796 curproxy->expect_str = strdup(args[cur_arg + 1]);
3797 }
3798 else if (strcmp(ptr_arg, "rstatus") == 0) {
3799 if (!*(args[cur_arg + 1])) {
3800 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3801 file, linenum, args[0], args[1], ptr_arg);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
3805 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003806 free(curproxy->expect_str);
3807 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3808 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003809 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3810 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3811 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3812 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
3816 }
3817 else if (strcmp(ptr_arg, "rstring") == 0) {
3818 if (!*(args[cur_arg + 1])) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3820 file, linenum, args[0], args[1], ptr_arg);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003825 free(curproxy->expect_str);
3826 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3827 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003828 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3829 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3830 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3831 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835 }
3836 else {
3837 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3838 file, linenum, args[0], args[1], ptr_arg);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003843 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003844 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 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003847 }
3848 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003849 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003850 if (curproxy == &defproxy) {
3851 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003854 }
3855
Willy Tarreaub80c2302007-11-30 20:51:32 +01003856 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003858
3859 if (strcmp(args[1], "fail") == 0) {
3860 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003861 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3863 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003866 }
3867
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003868 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3869 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3870 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003873 }
3874 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3875 }
3876 else {
3877 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003880 }
3881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882#ifdef TPROXY
3883 else if (!strcmp(args[0], "transparent")) {
3884 /* enable transparent proxy connections */
3885 curproxy->options |= PR_O_TRANSP;
3886 }
3887#endif
3888 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 if (*(args[1]) == 0) {
3893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003896 }
3897 curproxy->maxconn = atol(args[1]);
3898 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003899 else if (!strcmp(args[0], "backlog")) { /* backlog */
3900 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003902
3903 if (*(args[1]) == 0) {
3904 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003907 }
3908 curproxy->backlog = atol(args[1]);
3909 }
Willy Tarreau86034312006-12-29 00:10:33 +01003910 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003913
Willy Tarreau86034312006-12-29 00:10:33 +01003914 if (*(args[1]) == 0) {
3915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003918 }
3919 curproxy->fullconn = atol(args[1]);
3920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3922 if (*(args[1]) == 0) {
3923 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003927 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3928 if (err) {
3929 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3930 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003933 }
3934 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 }
3936 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003937 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 if (curproxy == &defproxy) {
3939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (strchr(args[1], ':') == NULL) {
3947 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003951 sk = str2sa(args[1]);
3952 if (!sk) {
3953 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003958 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
3960 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003963
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003964 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3965 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003970 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3972 err_code |= ERR_WARN;
3973
3974 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3975 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3976 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3977 }
3978 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3979 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3980 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3981 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003982 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3983 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3984 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3985 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003986 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003987 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990 }
3991 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003993 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994 char *rport, *raddr;
3995 short realport = 0;
3996 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003998 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004003 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005
4006 if (!*args[2]) {
4007 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004012
4013 err = invalid_char(args[1]);
4014 if (err) {
4015 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4016 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004017 err_code |= ERR_ALERT | ERR_FATAL;
4018 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004019 }
4020
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004022 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004023
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004024 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4026 err_code |= ERR_ALERT | ERR_ABORT;
4027 goto out;
4028 }
4029
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 /* the servers are linked backwards first */
4031 newsrv->next = curproxy->srv;
4032 curproxy->srv = newsrv;
4033 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004034 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004035 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036
Simon Hormanaf514952011-06-21 14:34:57 +09004037 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004038 LIST_INIT(&newsrv->pendconns);
4039 do_check = 0;
4040 newsrv->state = SRV_RUNNING; /* early server setup */
4041 newsrv->last_change = now.tv_sec;
4042 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004044 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004045 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 * - IP: => port=+0, relative
4047 * - IP:N => port=N, absolute
4048 * - IP:+N => port=+N, relative
4049 * - IP:-N => port=-N, relative
4050 */
4051 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004052 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004053 if (rport) {
4054 *rport++ = 0;
4055 realport = atol(rport);
4056 if (!isdigit((unsigned char)*rport))
4057 newsrv->state |= SRV_MAPPORTS;
4058 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004060
Willy Tarreaufab5a432011-03-04 15:31:53 +01004061 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004062 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004063 if (!sk) {
4064 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004069 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4070 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004071
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004072 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004073 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4074 file, linenum, newsrv->addr.ss_family, args[2]);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004078 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004080 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004081 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004082 newsrv->inter = curproxy->defsrv.inter;
4083 newsrv->fastinter = curproxy->defsrv.fastinter;
4084 newsrv->downinter = curproxy->defsrv.downinter;
4085 newsrv->rise = curproxy->defsrv.rise;
4086 newsrv->fall = curproxy->defsrv.fall;
4087 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4088 newsrv->minconn = curproxy->defsrv.minconn;
4089 newsrv->maxconn = curproxy->defsrv.maxconn;
4090 newsrv->slowstart = curproxy->defsrv.slowstart;
4091 newsrv->onerror = curproxy->defsrv.onerror;
4092 newsrv->consecutive_errors_limit
4093 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004094#ifdef OPENSSL
4095 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4096#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004097 newsrv->uweight = newsrv->iweight
4098 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004101
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 cur_arg = 3;
4103 } else {
4104 newsrv = &curproxy->defsrv;
4105 cur_arg = 1;
4106 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004107
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004109 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 newsrv->cookie = strdup(args[cur_arg + 1]);
4111 newsrv->cklen = strlen(args[cur_arg + 1]);
4112 cur_arg += 2;
4113 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004115 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4116 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4117 cur_arg += 2;
4118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004120 if (!*args[cur_arg + 1]) {
4121 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4122 file, linenum, args[cur_arg]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004128 if (newsrv->rise <= 0) {
4129 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4130 file, linenum, args[cur_arg]);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
4134
Willy Tarreau96839092010-03-29 10:02:24 +02004135 if (newsrv->health)
4136 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 cur_arg += 2;
4138 }
4139 else if (!strcmp(args[cur_arg], "fall")) {
4140 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004141
4142 if (!*args[cur_arg + 1]) {
4143 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4144 file, linenum, args[cur_arg]);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148
4149 if (newsrv->fall <= 0) {
4150 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4151 file, linenum, args[cur_arg]);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004159 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4160 if (err) {
4161 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4162 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004165 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004166 if (val <= 0) {
4167 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4168 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004171 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004172 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 cur_arg += 2;
4174 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004175 else if (!strcmp(args[cur_arg], "fastinter")) {
4176 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4177 if (err) {
4178 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4179 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004182 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004183 if (val <= 0) {
4184 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4185 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004188 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004189 newsrv->fastinter = val;
4190 cur_arg += 2;
4191 }
4192 else if (!strcmp(args[cur_arg], "downinter")) {
4193 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4194 if (err) {
4195 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4196 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004199 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004200 if (val <= 0) {
4201 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4202 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004205 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004206 newsrv->downinter = val;
4207 cur_arg += 2;
4208 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004210 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004211 if (!sk) {
4212 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004216 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004217 cur_arg += 2;
4218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004220 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004221 cur_arg += 2;
4222 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004223 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 newsrv->state |= SRV_BACKUP;
4225 cur_arg ++;
4226 }
Simon Hormanfa461682011-06-25 09:39:49 +09004227 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4228 newsrv->state |= SRV_NON_STICK;
4229 cur_arg ++;
4230 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004231 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4232 newsrv->state |= SRV_SEND_PROXY;
4233 cur_arg ++;
4234 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004235 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4236 newsrv->check.send_proxy = 1;
4237 cur_arg ++;
4238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 else if (!strcmp(args[cur_arg], "weight")) {
4240 int w;
4241 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004242 if (w < 0 || w > 256) {
4243 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004247 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004248 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 cur_arg += 2;
4250 }
4251 else if (!strcmp(args[cur_arg], "minconn")) {
4252 newsrv->minconn = atol(args[cur_arg + 1]);
4253 cur_arg += 2;
4254 }
4255 else if (!strcmp(args[cur_arg], "maxconn")) {
4256 newsrv->maxconn = atol(args[cur_arg + 1]);
4257 cur_arg += 2;
4258 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004259 else if (!strcmp(args[cur_arg], "maxqueue")) {
4260 newsrv->maxqueue = atol(args[cur_arg + 1]);
4261 cur_arg += 2;
4262 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004263 else if (!strcmp(args[cur_arg], "slowstart")) {
4264 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004265 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004266 if (err) {
4267 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4268 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004271 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004272 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004273 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4274 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004277 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004278 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004279 cur_arg += 2;
4280 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004281 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004282
4283 if (!*args[cur_arg + 1]) {
4284 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4285 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004288 }
4289
4290 newsrv->trackit = strdup(args[cur_arg + 1]);
4291
4292 cur_arg += 2;
4293 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004294 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 global.maxsock++;
4296 do_check = 1;
4297 cur_arg += 1;
4298 }
Willy Tarreau96839092010-03-29 10:02:24 +02004299 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4300 newsrv->state |= SRV_MAINTAIN;
4301 newsrv->state &= ~SRV_RUNNING;
4302 newsrv->health = 0;
4303 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004304 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004305 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004306 if (!strcmp(args[cur_arg + 1], "none"))
4307 newsrv->observe = HANA_OBS_NONE;
4308 else if (!strcmp(args[cur_arg + 1], "layer4"))
4309 newsrv->observe = HANA_OBS_LAYER4;
4310 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4311 if (curproxy->mode != PR_MODE_HTTP) {
4312 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4313 file, linenum, args[cur_arg + 1]);
4314 err_code |= ERR_ALERT;
4315 }
4316 newsrv->observe = HANA_OBS_LAYER7;
4317 }
4318 else {
4319 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004320 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004321 file, linenum, args[cur_arg], args[cur_arg + 1]);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
4325
4326 cur_arg += 2;
4327 }
4328 else if (!strcmp(args[cur_arg], "on-error")) {
4329 if (!strcmp(args[cur_arg + 1], "fastinter"))
4330 newsrv->onerror = HANA_ONERR_FASTINTER;
4331 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4332 newsrv->onerror = HANA_ONERR_FAILCHK;
4333 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4334 newsrv->onerror = HANA_ONERR_SUDDTH;
4335 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4336 newsrv->onerror = HANA_ONERR_MARKDWN;
4337 else {
4338 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004339 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004340 file, linenum, args[cur_arg], args[cur_arg + 1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344
4345 cur_arg += 2;
4346 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004347 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4348 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4349 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4350 else {
4351 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4352 file, linenum, args[cur_arg], args[cur_arg + 1]);
4353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
4355 }
4356
4357 cur_arg += 2;
4358 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004359 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4360 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4361 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4362 else {
4363 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4364 file, linenum, args[cur_arg], args[cur_arg + 1]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
4368
4369 cur_arg += 2;
4370 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004371 else if (!strcmp(args[cur_arg], "error-limit")) {
4372 if (!*args[cur_arg + 1]) {
4373 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4374 file, linenum, args[cur_arg]);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
4378
4379 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4380
4381 if (newsrv->consecutive_errors_limit <= 0) {
4382 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4383 file, linenum, args[cur_arg]);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004387 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004388 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004389 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004390 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004391 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004392
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004394#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004395 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004396 file, linenum, "source", "usesrc");
4397#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004398 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004400#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
4404 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004405 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4406 if (!sk) {
4407 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
4410 }
4411 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004412
4413 if (port_low != port_high) {
4414 int i;
4415 if (port_low <= 0 || port_low > 65535 ||
4416 port_high <= 0 || port_high > 65535 ||
4417 port_low > port_high) {
4418 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4419 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004422 }
4423 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4424 for (i = 0; i < newsrv->sport_range->size; i++)
4425 newsrv->sport_range->ports[i] = port_low + i;
4426 }
4427
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 while (*(args[cur_arg])) {
4430 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004431#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4432#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004433 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4434 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4435 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004439#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004440 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004441 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004445 }
4446 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004447 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004448 newsrv->state |= SRV_TPROXY_CLI;
4449 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004450 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004451 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004452 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4453 char *name, *end;
4454
4455 name = args[cur_arg+1] + 7;
4456 while (isspace(*name))
4457 name++;
4458
4459 end = name;
4460 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4461 end++;
4462
4463 newsrv->state &= ~SRV_TPROXY_MASK;
4464 newsrv->state |= SRV_TPROXY_DYN;
4465 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4466 newsrv->bind_hdr_len = end - name;
4467 memcpy(newsrv->bind_hdr_name, name, end - name);
4468 newsrv->bind_hdr_name[end-name] = '\0';
4469 newsrv->bind_hdr_occ = -1;
4470
4471 /* now look for an occurrence number */
4472 while (isspace(*end))
4473 end++;
4474 if (*end == ',') {
4475 end++;
4476 name = end;
4477 if (*end == '-')
4478 end++;
4479 while (isdigit(*end))
4480 end++;
4481 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4482 }
4483
4484 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4485 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4486 " occurrences values smaller than %d.\n",
4487 file, linenum, MAX_HDR_HISTORY);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004491 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004492 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004493 if (!sk) {
4494 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
4497 }
4498 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004499 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004500 }
4501 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004502#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004503 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004504#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505 cur_arg += 2;
4506 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004507#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004508 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004509 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004512#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4513 } /* "usesrc" */
4514
4515 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4516#ifdef SO_BINDTODEVICE
4517 if (!*args[cur_arg + 1]) {
4518 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004520 err_code |= ERR_ALERT | ERR_FATAL;
4521 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004522 }
4523 if (newsrv->iface_name)
4524 free(newsrv->iface_name);
4525
4526 newsrv->iface_name = strdup(args[cur_arg + 1]);
4527 newsrv->iface_len = strlen(newsrv->iface_name);
4528 global.last_checks |= LSTCHK_NETADM;
4529#else
4530 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4531 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004534#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004535 cur_arg += 2;
4536 continue;
4537 }
4538 /* this keyword in not an option of "source" */
4539 break;
4540 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004542 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004543 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4544 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004545 err_code |= ERR_ALERT | ERR_FATAL;
4546 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004547 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004549 static int srv_dumped;
4550 struct srv_kw *kw;
4551 char *err;
4552
4553 kw = srv_find_kw(args[cur_arg]);
4554 if (kw) {
4555 char *err = NULL;
4556 int code;
4557
4558 if (!kw->parse) {
4559 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4560 file, linenum, args[0], args[1], args[cur_arg]);
4561 cur_arg += 1 + kw->skip ;
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
4565
4566 if (defsrv && !kw->default_ok) {
4567 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4568 file, linenum, args[0], args[1], args[cur_arg]);
4569 cur_arg += 1 + kw->skip ;
4570 err_code |= ERR_ALERT;
4571 continue;
4572 }
4573
4574 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4575 err_code |= code;
4576
4577 if (code) {
4578 if (err && *err) {
4579 indent_msg(&err, 2);
4580 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4581 }
4582 else
4583 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4584 file, linenum, args[0], args[1], args[cur_arg]);
4585 if (code & ERR_FATAL) {
4586 free(err);
4587 cur_arg += 1 + kw->skip;
4588 goto out;
4589 }
4590 }
4591 free(err);
4592 cur_arg += 1 + kw->skip;
4593 continue;
4594 }
4595
4596 err = NULL;
4597 if (!srv_dumped) {
4598 srv_dump_kws(&err);
4599 indent_msg(&err, 4);
4600 srv_dumped = 1;
4601 }
4602
4603 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4604 file, linenum, args[0], args[1], args[cur_arg],
4605 err ? " Registered keywords :" : "", err ? err : "");
4606 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004607
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 }
4611 }
4612
4613 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004614 if (newsrv->trackit) {
4615 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4616 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004619 }
4620
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004621 /* If neither a port nor an addr was specified and no check transport
4622 * layer is forced, then the transport layer used by the checks is the
4623 * same as for the production traffic. Otherwise we use raw_sock by
4624 * default, unless one is specified.
4625 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004626 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004627#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004628 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004629#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004630 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4631 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004632 /* try to get the port from check.addr if check.port not set */
4633 if (!newsrv->check.port)
4634 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004635
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004636 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4637 newsrv->check.port = realport; /* by default */
4638 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004639 /* not yet valid, because no port was set on
4640 * the server either. We'll check if we have
4641 * a known port on the first listener.
4642 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004643 struct listener *l;
4644
4645 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004646 newsrv->check.port = get_host_port(&l->addr);
4647 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004648 break;
4649 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004650 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004651 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4653 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004657
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004658 /* Allocate buffer for check requests... */
4659 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004660 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4661 err_code |= ERR_ALERT | ERR_ABORT;
4662 goto out;
4663 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004664 newsrv->check.bi->size = global.tune.chksize;
4665
4666 /* Allocate buffer for check responses... */
4667 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4668 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4669 err_code |= ERR_ALERT | ERR_ABORT;
4670 goto out;
4671 }
4672 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004673
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004674 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004675 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004676 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4677 err_code |= ERR_ALERT | ERR_ABORT;
4678 goto out;
4679 }
4680
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004681 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4682 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004683 newsrv->state |= SRV_CHECKED;
4684 }
4685
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004686 if (!defsrv) {
4687 if (newsrv->state & SRV_BACKUP)
4688 curproxy->srv_bck++;
4689 else
4690 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004691
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004692 newsrv->prev_state = newsrv->state;
4693 }
William Lallemanda73203e2012-03-12 12:48:57 +01004694 }
4695
4696 else if (strcmp(args[0], "unique-id-format") == 0) {
4697 if (!*(args[1])) {
4698 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
William Lallemand3203ff42012-11-11 17:30:56 +01004702 if (*(args[2])) {
4703 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
4706 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004707 free(curproxy->uniqueid_format_string);
4708 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004709 }
William Lallemanda73203e2012-03-12 12:48:57 +01004710
4711 else if (strcmp(args[0], "unique-id-header") == 0) {
4712 if (!*(args[1])) {
4713 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
4717 free(curproxy->header_unique_id);
4718 curproxy->header_unique_id = strdup(args[1]);
4719 }
4720
William Lallemand723b73a2012-02-08 16:37:49 +01004721 else if (strcmp(args[0], "log-format") == 0) {
4722 if (!*(args[1])) {
4723 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
William Lallemand3203ff42012-11-11 17:30:56 +01004727 if (*(args[2])) {
4728 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4729 err_code |= ERR_ALERT | ERR_FATAL;
4730 goto out;
4731 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004732
4733 if (curproxy->logformat_string != default_http_log_format &&
4734 curproxy->logformat_string != default_tcp_log_format &&
4735 curproxy->logformat_string != clf_http_log_format)
4736 free(curproxy->logformat_string);
4737 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
William Lallemand723b73a2012-02-08 16:37:49 +01004739
William Lallemand0f99e342011-10-12 17:50:54 +02004740 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4741 /* delete previous herited or defined syslog servers */
4742 struct logsrv *back;
4743
4744 if (*(args[1]) != 0) {
4745 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
4749
William Lallemand723b73a2012-02-08 16:37:49 +01004750 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4751 LIST_DEL(&tmplogsrv->list);
4752 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004753 }
4754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004756 struct logsrv *logsrv;
4757
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004759 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004760 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004761 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004762 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004763 LIST_INIT(&node->list);
4764 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004766 }
4767 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004768
4769 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770
William Lallemand0f99e342011-10-12 17:50:54 +02004771 logsrv->facility = get_log_facility(args[2]);
4772 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
4778
William Lallemand0f99e342011-10-12 17:50:54 +02004779 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004781 logsrv->level = get_log_level(args[3]);
4782 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
4788 }
4789
William Lallemand0f99e342011-10-12 17:50:54 +02004790 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004791 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004792 logsrv->minlvl = get_log_level(args[4]);
4793 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004794 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
4797
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004798 }
4799 }
4800
Robert Tsai81ae1952007-12-05 10:47:29 +01004801 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004802 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004803 if (!sk) {
4804 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004805 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
William Lallemand0f99e342011-10-12 17:50:54 +02004809 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004810 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004811 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004812 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004813 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
William Lallemand0f99e342011-10-12 17:50:54 +02004817 logsrv->addr = *sk;
4818 if (!get_host_port(&logsrv->addr))
4819 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
William Lallemand0f99e342011-10-12 17:50:54 +02004821
4822 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
4824 else {
4825 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4826 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 }
4830 }
4831 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004833 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834
Willy Tarreau977b8e42006-12-29 14:19:17 +01004835 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004837
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4840 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004844
4845 /* we must first clear any optional default setting */
4846 curproxy->options &= ~PR_O_TPXY_MASK;
4847 free(curproxy->iface_name);
4848 curproxy->iface_name = NULL;
4849 curproxy->iface_len = 0;
4850
Willy Tarreaud5191e72010-02-09 20:50:45 +01004851 sk = str2sa(args[1]);
4852 if (!sk) {
4853 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
4856 }
4857 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004859
4860 cur_arg = 2;
4861 while (*(args[cur_arg])) {
4862 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004863#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4864#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004865 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4866 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4867 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 }
4871#endif
4872 if (!*args[cur_arg + 1]) {
4873 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4874 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004877 }
4878
4879 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004880 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004881 curproxy->options |= PR_O_TPXY_CLI;
4882 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004883 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004884 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004885 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4886 char *name, *end;
4887
4888 name = args[cur_arg+1] + 7;
4889 while (isspace(*name))
4890 name++;
4891
4892 end = name;
4893 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4894 end++;
4895
4896 curproxy->options &= ~PR_O_TPXY_MASK;
4897 curproxy->options |= PR_O_TPXY_DYN;
4898 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4899 curproxy->bind_hdr_len = end - name;
4900 memcpy(curproxy->bind_hdr_name, name, end - name);
4901 curproxy->bind_hdr_name[end-name] = '\0';
4902 curproxy->bind_hdr_occ = -1;
4903
4904 /* now look for an occurrence number */
4905 while (isspace(*end))
4906 end++;
4907 if (*end == ',') {
4908 end++;
4909 name = end;
4910 if (*end == '-')
4911 end++;
4912 while (isdigit(*end))
4913 end++;
4914 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4915 }
4916
4917 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4918 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4919 " occurrences values smaller than %d.\n",
4920 file, linenum, MAX_HDR_HISTORY);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004925 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004926 if (!sk) {
4927 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
4930 }
4931 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004932 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004933 }
4934 global.last_checks |= LSTCHK_NETADM;
4935#if !defined(CONFIG_HAP_LINUX_TPROXY)
4936 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004937#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004938#else /* no TPROXY support */
4939 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004940 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004943#endif
4944 cur_arg += 2;
4945 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004946 }
4947
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4949#ifdef SO_BINDTODEVICE
4950 if (!*args[cur_arg + 1]) {
4951 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4952 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004955 }
4956 if (curproxy->iface_name)
4957 free(curproxy->iface_name);
4958
4959 curproxy->iface_name = strdup(args[cur_arg + 1]);
4960 curproxy->iface_len = strlen(curproxy->iface_name);
4961 global.last_checks |= LSTCHK_NETADM;
4962#else
4963 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4964 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004967#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004968 cur_arg += 2;
4969 continue;
4970 }
4971 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004972 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004977 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4978 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4979 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004983 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4986 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990
4991 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004992 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004993 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004994 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996 }
4997 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004999 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005000 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005001 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005006 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005007 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005008 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
5011 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005013 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005014 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005015 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
5018 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005019 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005020 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005021 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005025 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005027 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005028 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005029 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005030 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005031 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005032 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005034 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005035 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005036 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005037 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005038 }
5039 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005041 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005042 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005043 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005044 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5049 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005052 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053
5054 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005055 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005056 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005057 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
5060 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005062 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005063 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005064 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
5067 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005068 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005069 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005070 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005071 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 }
5074 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005075 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005076 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005077 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005078 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
5081 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005082 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005083 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005084 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005085 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005088 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005089 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005090 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005091 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005092 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005093 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005094 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005095 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005096 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005097
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 if (curproxy == &defproxy) {
5099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005103 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105
Willy Tarreaubaaee002006-06-26 02:48:02 +02005106 if (*(args[1]) == 0) {
5107 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005111
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005112 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005113 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5114 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5115 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
5118 }
5119 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5120 }
5121 else if (*args[2]) {
5122 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5123 file, linenum, args[0], args[2]);
5124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
5126 }
5127
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005128 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005129 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005130 wl->s = strdup(args[1]);
5131 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005132 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
5134 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005135 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5137 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005141
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005143 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005144 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
5148 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005150 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005151 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
5155 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005158 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5165 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 }
5169
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005171 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005172 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
5176 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005178 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005179 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 }
5183 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005185 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005186 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005189 }
5190 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005191 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005192
Willy Tarreaubaaee002006-06-26 02:48:02 +02005193 if (curproxy == &defproxy) {
5194 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005198 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 if (*(args[1]) == 0) {
5202 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005207 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005208 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5209 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5210 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214 err_code |= warnif_cond_requires_req(cond, file, linenum);
5215 }
5216 else if (*args[2]) {
5217 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5218 file, linenum, args[0], args[2]);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005223 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005224 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005225 wl->s = strdup(args[1]);
5226 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
5228 else if (!strcmp(args[0], "errorloc") ||
5229 !strcmp(args[0], "errorloc302") ||
5230 !strcmp(args[0], "errorloc303")) { /* error location */
5231 int errnum, errlen;
5232 char *err;
5233
Willy Tarreau977b8e42006-12-29 14:19:17 +01005234 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005236
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005238 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005241 }
5242
5243 errnum = atol(args[1]);
5244 if (!strcmp(args[0], "errorloc303")) {
5245 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5246 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5247 } else {
5248 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5249 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5250 }
5251
Willy Tarreau0f772532006-12-23 20:51:41 +01005252 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5253 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005254 chunk_destroy(&curproxy->errmsg[rc]);
5255 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005256 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005259
5260 if (rc >= HTTP_ERR_SIZE) {
5261 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5262 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 free(err);
5264 }
5265 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005266 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5267 int errnum, errlen, fd;
5268 char *err;
5269 struct stat stat;
5270
5271 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005273
5274 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005275 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005278 }
5279
5280 fd = open(args[2], O_RDONLY);
5281 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5282 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5283 file, linenum, args[2], args[1]);
5284 if (fd >= 0)
5285 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005288 }
5289
Willy Tarreau27a674e2009-08-17 07:23:33 +02005290 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005291 errlen = stat.st_size;
5292 } else {
5293 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005294 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005295 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005296 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005297 }
5298
5299 err = malloc(errlen); /* malloc() must succeed during parsing */
5300 errnum = read(fd, err, errlen);
5301 if (errnum != errlen) {
5302 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5303 file, linenum, args[2], args[1]);
5304 close(fd);
5305 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005308 }
5309 close(fd);
5310
5311 errnum = atol(args[1]);
5312 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5313 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005314 chunk_destroy(&curproxy->errmsg[rc]);
5315 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005316 break;
5317 }
5318 }
5319
5320 if (rc >= HTTP_ERR_SIZE) {
5321 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5322 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005323 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005324 free(err);
5325 }
5326 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005327 else if (!strcmp(args[0], "compression")) {
5328 struct comp *comp;
5329 if (curproxy->comp == NULL) {
5330 comp = calloc(1, sizeof(struct comp));
5331 curproxy->comp = comp;
5332 } else {
5333 comp = curproxy->comp;
5334 }
5335
5336 if (!strcmp(args[1], "algo")) {
5337 int cur_arg;
William Lallemand552df672012-11-07 13:21:47 +01005338 struct comp_ctx ctx;
5339
William Lallemand82fe75c2012-10-23 10:25:10 +02005340 cur_arg = 2;
5341 if (!*args[cur_arg]) {
5342 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5343 file, linenum, args[0]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347 while (*(args[cur_arg])) {
5348 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5349 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5350 file, linenum, args[0], args[cur_arg]);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
William Lallemand552df672012-11-07 13:21:47 +01005354 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5355 curproxy->comp->algos->end(&ctx);
5356 } else {
5357 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5358 file, linenum, args[0], args[cur_arg]);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005362 cur_arg ++;
5363 continue;
5364 }
5365 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005366 else if (!strcmp(args[1], "offload")) {
5367 comp->offload = 1;
5368 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005369 else if (!strcmp(args[1], "type")) {
5370 int cur_arg;
5371 cur_arg = 2;
5372 if (!*args[cur_arg]) {
5373 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5374 file, linenum, args[0]);
5375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378 while (*(args[cur_arg])) {
5379 comp_append_type(comp, args[cur_arg]);
5380 cur_arg ++;
5381 continue;
5382 }
5383 }
5384 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005385 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005386 file, linenum, args[0]);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005392 struct cfg_kw_list *kwl;
5393 int index;
5394
5395 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5396 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5397 if (kwl->kw[index].section != CFG_LISTEN)
5398 continue;
5399 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5400 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005401 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005402 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005403 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005406 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005407 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005408 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_WARN;
5410 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005411 }
Willy Tarreau93893792009-07-23 13:19:11 +02005412 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005413 }
5414 }
5415 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005416
Willy Tarreau6daf3432008-01-22 16:44:08 +01005417 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005418 err_code |= ERR_ALERT | ERR_FATAL;
5419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 }
Willy Tarreau93893792009-07-23 13:19:11 +02005421 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005422 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005423 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424}
5425
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005426int
5427cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5428{
5429
5430 int err_code = 0;
5431 const char *err;
5432
5433 if (!strcmp(args[0], "userlist")) { /* new userlist */
5434 struct userlist *newul;
5435
5436 if (!*args[1]) {
5437 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5438 file, linenum, args[0]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442
5443 err = invalid_char(args[1]);
5444 if (err) {
5445 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5446 file, linenum, *err, args[0], args[1]);
5447 err_code |= ERR_ALERT | ERR_FATAL;
5448 goto out;
5449 }
5450
5451 for (newul = userlist; newul; newul = newul->next)
5452 if (!strcmp(newul->name, args[1])) {
5453 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5454 file, linenum, args[1]);
5455 err_code |= ERR_WARN;
5456 goto out;
5457 }
5458
5459 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5460 if (!newul) {
5461 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5462 err_code |= ERR_ALERT | ERR_ABORT;
5463 goto out;
5464 }
5465
5466 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5467 newul->name = strdup(args[1]);
5468
5469 if (!newul->groupusers | !newul->name) {
5470 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5471 err_code |= ERR_ALERT | ERR_ABORT;
5472 goto out;
5473 }
5474
5475 newul->next = userlist;
5476 userlist = newul;
5477
5478 } else if (!strcmp(args[0], "group")) { /* new group */
5479 int cur_arg, i;
5480 const char *err;
5481
5482 if (!*args[1]) {
5483 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5484 file, linenum, args[0]);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
5488
5489 err = invalid_char(args[1]);
5490 if (err) {
5491 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5492 file, linenum, *err, args[0], args[1]);
5493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
5496
5497 for(i = 0; i < userlist->grpcnt; i++)
5498 if (!strcmp(userlist->groups[i], args[1])) {
5499 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5500 file, linenum, args[1], userlist->name);
5501 err_code |= ERR_ALERT;
5502 goto out;
5503 }
5504
5505 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5506 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5507 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
5510 }
5511
5512 cur_arg = 2;
5513
5514 while (*args[cur_arg]) {
5515 if (!strcmp(args[cur_arg], "users")) {
5516 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5517 cur_arg += 2;
5518 continue;
5519 } else {
5520 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5521 file, linenum, args[0]);
5522 err_code |= ERR_ALERT | ERR_FATAL;
5523 goto out;
5524 }
5525 }
5526
5527 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5528 } else if (!strcmp(args[0], "user")) { /* new user */
5529 struct auth_users *newuser;
5530 int cur_arg;
5531
5532 if (!*args[1]) {
5533 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5534 file, linenum, args[0]);
5535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537 }
5538
5539 for (newuser = userlist->users; newuser; newuser = newuser->next)
5540 if (!strcmp(newuser->user, args[1])) {
5541 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5542 file, linenum, args[1], userlist->name);
5543 err_code |= ERR_ALERT;
5544 goto out;
5545 }
5546
5547 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5548 if (!newuser) {
5549 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5550 err_code |= ERR_ALERT | ERR_ABORT;
5551 goto out;
5552 }
5553
5554 newuser->user = strdup(args[1]);
5555
5556 newuser->next = userlist->users;
5557 userlist->users = newuser;
5558
5559 cur_arg = 2;
5560
5561 while (*args[cur_arg]) {
5562 if (!strcmp(args[cur_arg], "password")) {
5563#ifndef CONFIG_HAP_CRYPT
5564 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5565 file, linenum);
5566 err_code |= ERR_ALERT;
5567#endif
5568 newuser->pass = strdup(args[cur_arg + 1]);
5569 cur_arg += 2;
5570 continue;
5571 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5572 newuser->pass = strdup(args[cur_arg + 1]);
5573 newuser->flags |= AU_O_INSECURE;
5574 cur_arg += 2;
5575 continue;
5576 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005577 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005578 cur_arg += 2;
5579 continue;
5580 } else {
5581 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5582 file, linenum, args[0]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586 }
5587 } else {
5588 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5589 err_code |= ERR_ALERT | ERR_FATAL;
5590 }
5591
5592out:
5593 return err_code;
5594}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595
5596/*
5597 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005598 * Returns the error code, 0 if OK, or any combination of :
5599 * - ERR_ABORT: must abort ASAP
5600 * - ERR_FATAL: we can continue parsing but not start the service
5601 * - ERR_WARN: a warning has been emitted
5602 * - ERR_ALERT: an alert has been emitted
5603 * Only the two first ones can stop processing, the two others are just
5604 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005606int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005608 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 FILE *f;
5610 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005612 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 if ((f=fopen(file,"r")) == NULL)
5615 return -1;
5616
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005617 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005618 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005619 char *end;
5620 char *args[MAX_LINE_ARGS + 1];
5621 char *line = thisline;
5622
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 linenum++;
5624
5625 end = line + strlen(line);
5626
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005627 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5628 /* Check if we reached the limit and the last char is not \n.
5629 * Watch out for the last line without the terminating '\n'!
5630 */
5631 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005632 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005634 }
5635
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005637 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 line++;
5639
5640 arg = 0;
5641 args[arg] = line;
5642
5643 while (*line && arg < MAX_LINE_ARGS) {
5644 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5645 * C equivalent value. Other combinations left unchanged (eg: \1).
5646 */
5647 if (*line == '\\') {
5648 int skip = 0;
5649 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5650 *line = line[1];
5651 skip = 1;
5652 }
5653 else if (line[1] == 'r') {
5654 *line = '\r';
5655 skip = 1;
5656 }
5657 else if (line[1] == 'n') {
5658 *line = '\n';
5659 skip = 1;
5660 }
5661 else if (line[1] == 't') {
5662 *line = '\t';
5663 skip = 1;
5664 }
5665 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005666 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 unsigned char hex1, hex2;
5668 hex1 = toupper(line[2]) - '0';
5669 hex2 = toupper(line[3]) - '0';
5670 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5671 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5672 *line = (hex1<<4) + hex2;
5673 skip = 3;
5674 }
5675 else {
5676 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005677 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678 }
5679 }
5680 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005681 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 end -= skip;
5683 }
5684 line++;
5685 }
5686 else if (*line == '#' || *line == '\n' || *line == '\r') {
5687 /* end of string, end of loop */
5688 *line = 0;
5689 break;
5690 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005691 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005693 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005694 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 line++;
5696 args[++arg] = line;
5697 }
5698 else {
5699 line++;
5700 }
5701 }
5702
5703 /* empty line */
5704 if (!**args)
5705 continue;
5706
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005707 if (*line) {
5708 /* we had to stop due to too many args.
5709 * Let's terminate the string, print the offending part then cut the
5710 * last arg.
5711 */
5712 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5713 line++;
5714 *line = '\0';
5715
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005716 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005717 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 args[arg] = line;
5720 }
5721
Willy Tarreau540abe42007-05-02 20:50:16 +02005722 /* zero out remaining args and ensure that at least one entry
5723 * is zeroed out.
5724 */
5725 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 args[arg] = line;
5727 }
5728
Willy Tarreau3842f002009-06-14 11:39:52 +02005729 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005730 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005731 char *tmp;
5732
Willy Tarreau3842f002009-06-14 11:39:52 +02005733 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005734 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005735 for (arg=0; *args[arg+1]; arg++)
5736 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005737 *tmp = '\0'; // fix the next arg to \0
5738 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005739 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005740 else if (!strcmp(args[0], "default")) {
5741 kwm = KWM_DEF;
5742 for (arg=0; *args[arg+1]; arg++)
5743 args[arg] = args[arg+1]; // shift args after inversion
5744 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005745
William Lallemand0f99e342011-10-12 17:50:54 +02005746 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5747 strcmp(args[0], "log") != 0) {
5748 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005749 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005750 }
5751
Willy Tarreau977b8e42006-12-29 14:19:17 +01005752 if (!strcmp(args[0], "listen") ||
5753 !strcmp(args[0], "frontend") ||
5754 !strcmp(args[0], "backend") ||
5755 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005756 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005758 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005759 cursection = strdup(args[0]);
5760 }
5761 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005763 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005764 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005765 }
5766 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005767 confsect = CFG_USERLIST;
5768 free(cursection);
5769 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005770 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005771 else if (!strcmp(args[0], "peers")) {
5772 confsect = CFG_PEERS;
5773 free(cursection);
5774 cursection = strdup(args[0]);
5775 }
5776
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 /* else it's a section keyword */
5778
5779 switch (confsect) {
5780 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 break;
5783 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005784 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005786 case CFG_USERLIST:
5787 err_code |= cfg_parse_users(file, linenum, args, kwm);
5788 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005789 case CFG_PEERS:
5790 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5791 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005793 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005794 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005796
5797 if (err_code & ERR_ABORT)
5798 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005800 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005801 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005803 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005804}
5805
Willy Tarreaubb925012009-07-23 13:36:36 +02005806/*
5807 * Returns the error code, 0 if OK, or any combination of :
5808 * - ERR_ABORT: must abort ASAP
5809 * - ERR_FATAL: we can continue parsing but not start the service
5810 * - ERR_WARN: a warning has been emitted
5811 * - ERR_ALERT: an alert has been emitted
5812 * Only the two first ones can stop processing, the two others are just
5813 * indicators.
5814 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005815int check_config_validity()
5816{
5817 int cfgerr = 0;
5818 struct proxy *curproxy = NULL;
5819 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005820 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005821 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005822 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005823 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005825 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 /*
5827 * Now, check for the integrity of all that we have collected.
5828 */
5829
5830 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005831 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005833 /* first, we will invert the proxy list order */
5834 curproxy = NULL;
5835 while (proxy) {
5836 struct proxy *next;
5837
5838 next = proxy->next;
5839 proxy->next = curproxy;
5840 curproxy = proxy;
5841 if (!next)
5842 break;
5843 proxy = next;
5844 }
5845
Willy Tarreaubaaee002006-06-26 02:48:02 +02005846 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005847 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005848 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005849 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005850 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005851 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005852 unsigned int next_id;
5853
Willy Tarreau050536d2012-10-04 08:47:34 +02005854 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005855 /* proxy ID not set, use automatic numbering with first
5856 * spare entry starting with next_pxid.
5857 */
5858 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5859 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5860 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005861 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005862 next_pxid++;
5863
Willy Tarreau55ea7572007-06-17 19:56:27 +02005864
Willy Tarreaubaaee002006-06-26 02:48:02 +02005865 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005866 /* ensure we don't keep listeners uselessly bound */
5867 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 curproxy = curproxy->next;
5869 continue;
5870 }
5871
Willy Tarreauff01a212009-03-15 13:46:16 +01005872 switch (curproxy->mode) {
5873 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005874 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005875 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005876 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5877 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005878 cfgerr++;
5879 }
5880
5881 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005882 Warning("config : servers will be ignored for %s '%s'.\n",
5883 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005884 break;
5885
5886 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005887 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005888 break;
5889
5890 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005891 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005892 break;
5893 }
5894
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005895 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005896 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005897 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005898 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5899 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005900 cfgerr++;
5901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005903 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005904 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5905 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005906 cfgerr++;
5907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005909 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005910 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5911 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005912 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005913 }
5914 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005915 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005916 /* If no LB algo is set in a backend, and we're not in
5917 * transparent mode, dispatch mode nor proxy mode, we
5918 * want to use balance roundrobin by default.
5919 */
5920 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5921 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
5923 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005924
Willy Tarreau1620ec32011-08-06 17:05:02 +02005925 if (curproxy->options & PR_O_DISPATCH)
5926 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5927 else if (curproxy->options & PR_O_HTTP_PROXY)
5928 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5929 else if (curproxy->options & PR_O_TRANSP)
5930 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005931
Willy Tarreau1620ec32011-08-06 17:05:02 +02005932 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5933 if (curproxy->options & PR_O_DISABLE404) {
5934 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5935 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5936 err_code |= ERR_WARN;
5937 curproxy->options &= ~PR_O_DISABLE404;
5938 }
5939 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5940 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5941 "send-state", proxy_type_str(curproxy), curproxy->id);
5942 err_code |= ERR_WARN;
5943 curproxy->options &= ~PR_O2_CHK_SNDST;
5944 }
Willy Tarreauef781042010-01-27 11:53:01 +01005945 }
5946
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005947 /* if a default backend was specified, let's find it */
5948 if (curproxy->defbe.name) {
5949 struct proxy *target;
5950
Alex Williams96532db2009-11-01 21:27:13 -05005951 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005952 if (!target) {
5953 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5954 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005955 cfgerr++;
5956 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005957 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5958 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005959 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005960 } else {
5961 free(curproxy->defbe.name);
5962 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005963 /* we force the backend to be present on at least all of
5964 * the frontend's processes.
5965 */
5966 target->bind_proc = curproxy->bind_proc ?
5967 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005968
5969 /* Emit a warning if this proxy also has some servers */
5970 if (curproxy->srv) {
5971 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5972 curproxy->id);
5973 err_code |= ERR_WARN;
5974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 }
5976 }
5977
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005978 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005979 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5980 /* map jump target for ACT_SETBE in req_rep chain */
5981 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005982 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005983 struct proxy *target;
5984
Willy Tarreaua496b602006-12-17 23:15:24 +01005985 if (exp->action != ACT_SETBE)
5986 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005987
Alex Williams96532db2009-11-01 21:27:13 -05005988 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005989 if (!target) {
5990 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5991 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005992 cfgerr++;
5993 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005994 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5995 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005996 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005997 } else {
5998 free((void *)exp->replace);
5999 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006000 /* we force the backend to be present on at least all of
6001 * the frontend's processes.
6002 */
6003 target->bind_proc = curproxy->bind_proc ?
6004 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006005 }
6006 }
6007 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006008
6009 /* find the target proxy for 'use_backend' rules */
6010 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006011 struct proxy *target;
6012
Alex Williams96532db2009-11-01 21:27:13 -05006013 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006014
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006015 if (!target) {
6016 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6017 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006018 cfgerr++;
6019 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006020 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6021 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006022 cfgerr++;
6023 } else {
6024 free((void *)rule->be.name);
6025 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006026 /* we force the backend to be present on at least all of
6027 * the frontend's processes.
6028 */
6029 target->bind_proc = curproxy->bind_proc ?
6030 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006031 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006032 }
6033
6034 /* find the target proxy for 'use_backend' rules */
6035 list_for_each_entry(srule, &curproxy->server_rules, list) {
6036 struct server *target = findserver(curproxy, srule->srv.name);
6037
6038 if (!target) {
6039 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6040 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6041 cfgerr++;
6042 continue;
6043 }
6044 free((void *)srule->srv.name);
6045 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006046 }
6047
Emeric Brunb982a3d2010-01-04 15:45:53 +01006048 /* find the target table for 'stick' rules */
6049 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6050 struct proxy *target;
6051
Emeric Brun1d33b292010-01-04 15:47:17 +01006052 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6053 if (mrule->flags & STK_IS_STORE)
6054 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6055
Emeric Brunb982a3d2010-01-04 15:45:53 +01006056 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006057 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006058 else
6059 target = curproxy;
6060
6061 if (!target) {
6062 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6063 curproxy->id, mrule->table.name);
6064 cfgerr++;
6065 }
6066 else if (target->table.size == 0) {
6067 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6068 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6069 cfgerr++;
6070 }
Willy Tarreau12785782012-04-27 21:37:17 +02006071 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6072 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006073 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6074 cfgerr++;
6075 }
6076 else {
6077 free((void *)mrule->table.name);
6078 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006079 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006080 }
6081 }
6082
6083 /* find the target table for 'store response' rules */
6084 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6085 struct proxy *target;
6086
Emeric Brun1d33b292010-01-04 15:47:17 +01006087 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6088
Emeric Brunb982a3d2010-01-04 15:45:53 +01006089 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006090 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006091 else
6092 target = curproxy;
6093
6094 if (!target) {
6095 Alert("Proxy '%s': unable to find store table '%s'.\n",
6096 curproxy->id, mrule->table.name);
6097 cfgerr++;
6098 }
6099 else if (target->table.size == 0) {
6100 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6101 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6102 cfgerr++;
6103 }
Willy Tarreau12785782012-04-27 21:37:17 +02006104 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6105 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006106 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6107 cfgerr++;
6108 }
6109 else {
6110 free((void *)mrule->table.name);
6111 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006112 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006113 }
6114 }
6115
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006116 /* find the target table for 'tcp-request' layer 4 rules */
6117 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6118 struct proxy *target;
6119
Willy Tarreau56123282010-08-06 19:06:56 +02006120 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006121 continue;
6122
6123 if (trule->act_prm.trk_ctr.table.n)
6124 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6125 else
6126 target = curproxy;
6127
6128 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006129 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6130 curproxy->id, trule->act_prm.trk_ctr.table.n,
6131 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006132 cfgerr++;
6133 }
6134 else if (target->table.size == 0) {
6135 Alert("Proxy '%s': table '%s' used but not configured.\n",
6136 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6137 cfgerr++;
6138 }
6139 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006140 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 +02006141 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6142 cfgerr++;
6143 }
6144 else {
6145 free(trule->act_prm.trk_ctr.table.n);
6146 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006147 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006148 * to pass a list of counters to track and allocate them right here using
6149 * stktable_alloc_data_type().
6150 */
6151 }
6152 }
6153
Willy Tarreaud1f96522010-08-03 19:34:32 +02006154 /* find the target table for 'tcp-request' layer 6 rules */
6155 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6156 struct proxy *target;
6157
Willy Tarreau56123282010-08-06 19:06:56 +02006158 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006159 continue;
6160
6161 if (trule->act_prm.trk_ctr.table.n)
6162 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6163 else
6164 target = curproxy;
6165
6166 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006167 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6168 curproxy->id, trule->act_prm.trk_ctr.table.n,
6169 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006170 cfgerr++;
6171 }
6172 else if (target->table.size == 0) {
6173 Alert("Proxy '%s': table '%s' used but not configured.\n",
6174 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6175 cfgerr++;
6176 }
6177 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006178 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 +02006179 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6180 cfgerr++;
6181 }
6182 else {
6183 free(trule->act_prm.trk_ctr.table.n);
6184 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006185 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006186 * to pass a list of counters to track and allocate them right here using
6187 * stktable_alloc_data_type().
6188 */
6189 }
6190 }
6191
Emeric Brun32da3c42010-09-23 18:39:19 +02006192 if (curproxy->table.peers.name) {
6193 struct peers *curpeers = peers;
6194
6195 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6196 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6197 free((void *)curproxy->table.peers.name);
6198 curproxy->table.peers.p = peers;
6199 break;
6200 }
6201 }
6202
6203 if (!curpeers) {
6204 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6205 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006206 free((void *)curproxy->table.peers.name);
6207 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006208 cfgerr++;
6209 }
6210 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006211 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6212 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006213 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006214 cfgerr++;
6215 }
6216 }
6217
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006218 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006219 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006220 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6221 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6222 "proxy", curproxy->id);
6223 cfgerr++;
6224 goto out_uri_auth_compat;
6225 }
6226
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006227 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006228 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006229 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006230 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006231
Willy Tarreau95fa4692010-02-01 13:05:50 +01006232 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6233 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006234
6235 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006236 uri_auth_compat_req[i++] = "realm";
6237 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6238 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006239
Willy Tarreau95fa4692010-02-01 13:05:50 +01006240 uri_auth_compat_req[i++] = "unless";
6241 uri_auth_compat_req[i++] = "{";
6242 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6243 uri_auth_compat_req[i++] = "}";
6244 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006245
Willy Tarreauff011f22011-01-06 17:51:27 +01006246 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6247 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006248 cfgerr++;
6249 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006250 }
6251
Willy Tarreauff011f22011-01-06 17:51:27 +01006252 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006253
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006254 if (curproxy->uri_auth->auth_realm) {
6255 free(curproxy->uri_auth->auth_realm);
6256 curproxy->uri_auth->auth_realm = NULL;
6257 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006258
6259 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006260 }
6261out_uri_auth_compat:
6262
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006263 cfgerr += acl_find_targets(curproxy);
6264
Willy Tarreau2738a142006-07-08 17:28:09 +02006265 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006266 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006267 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006268 (!curproxy->timeout.connect ||
6269 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006270 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006271 " | While not properly invalid, you will certainly encounter various problems\n"
6272 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006273 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006274 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006275 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006276 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006277
Willy Tarreau1fa31262007-12-03 00:36:16 +01006278 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6279 * We must still support older configurations, so let's find out whether those
6280 * parameters have been set or must be copied from contimeouts.
6281 */
6282 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006283 if (!curproxy->timeout.tarpit ||
6284 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006285 /* tarpit timeout not set. We search in the following order:
6286 * default.tarpit, curr.connect, default.connect.
6287 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006288 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006289 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006290 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006291 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006292 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006293 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006294 }
6295 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006296 (!curproxy->timeout.queue ||
6297 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006298 /* queue timeout not set. We search in the following order:
6299 * default.queue, curr.connect, default.connect.
6300 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006301 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006302 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006303 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006304 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006305 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006306 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006307 }
6308 }
6309
Willy Tarreau1620ec32011-08-06 17:05:02 +02006310 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006311 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6312 curproxy->check_req = (char *)malloc(curproxy->check_len);
6313 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006314 }
6315
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006316 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006317 if (curproxy->nb_req_cap) {
6318 if (curproxy->mode == PR_MODE_HTTP) {
6319 curproxy->req_cap_pool = create_pool("ptrcap",
6320 curproxy->nb_req_cap * sizeof(char *),
6321 MEM_F_SHARED);
6322 } else {
6323 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6324 proxy_type_str(curproxy), curproxy->id);
6325 err_code |= ERR_WARN;
6326 curproxy->to_log &= ~LW_REQHDR;
6327 curproxy->nb_req_cap = 0;
6328 }
6329 }
6330
6331 if (curproxy->nb_rsp_cap) {
6332 if (curproxy->mode == PR_MODE_HTTP) {
6333 curproxy->rsp_cap_pool = create_pool("ptrcap",
6334 curproxy->nb_rsp_cap * sizeof(char *),
6335 MEM_F_SHARED);
6336 } else {
6337 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6338 proxy_type_str(curproxy), curproxy->id);
6339 err_code |= ERR_WARN;
6340 curproxy->to_log &= ~LW_REQHDR;
6341 curproxy->nb_rsp_cap = 0;
6342 }
6343 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006344
Willy Tarreau196729e2012-05-31 19:30:26 +02006345 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006346 if (!(curproxy->cap & PR_CAP_FE)) {
6347 if (curproxy->logformat_string != default_http_log_format &&
6348 curproxy->logformat_string != default_tcp_log_format &&
6349 curproxy->logformat_string != clf_http_log_format)
6350 free(curproxy->logformat_string);
6351 curproxy->logformat_string = NULL;
6352 }
6353
Willy Tarreau196729e2012-05-31 19:30:26 +02006354 if (curproxy->logformat_string)
6355 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6356
6357 if (curproxy->uniqueid_format_string)
6358 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6359
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 /* first, we will invert the servers list order */
6361 newsrv = NULL;
6362 while (curproxy->srv) {
6363 struct server *next;
6364
6365 next = curproxy->srv->next;
6366 curproxy->srv->next = newsrv;
6367 newsrv = curproxy->srv;
6368 if (!next)
6369 break;
6370 curproxy->srv = next;
6371 }
6372
Willy Tarreaudd701652010-05-25 23:03:02 +02006373 /* assign automatic UIDs to servers which don't have one yet */
6374 next_id = 1;
6375 newsrv = curproxy->srv;
6376 while (newsrv != NULL) {
6377 if (!newsrv->puid) {
6378 /* server ID not set, use automatic numbering with first
6379 * spare entry starting with next_svid.
6380 */
6381 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6382 newsrv->conf.id.key = newsrv->puid = next_id;
6383 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6384 }
6385 next_id++;
6386 newsrv = newsrv->next;
6387 }
6388
Willy Tarreau20697042007-11-15 23:26:18 +01006389 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006390 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391
Willy Tarreau62c3be22012-01-20 13:12:32 +01006392 /*
6393 * If this server supports a maxconn parameter, it needs a dedicated
6394 * tasks to fill the emptied slots when a connection leaves.
6395 * Also, resolve deferred tracking dependency if needed.
6396 */
6397 newsrv = curproxy->srv;
6398 while (newsrv != NULL) {
6399 if (newsrv->minconn > newsrv->maxconn) {
6400 /* Only 'minconn' was specified, or it was higher than or equal
6401 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6402 * this will avoid further useless expensive computations.
6403 */
6404 newsrv->maxconn = newsrv->minconn;
6405 } else if (newsrv->maxconn && !newsrv->minconn) {
6406 /* minconn was not specified, so we set it to maxconn */
6407 newsrv->minconn = newsrv->maxconn;
6408 }
6409
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006410#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006411 if (newsrv->use_ssl || newsrv->check.use_ssl)
6412 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006413#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006414
Willy Tarreau62c3be22012-01-20 13:12:32 +01006415 if (newsrv->trackit) {
6416 struct proxy *px;
6417 struct server *srv;
6418 char *pname, *sname;
6419
6420 pname = newsrv->trackit;
6421 sname = strrchr(pname, '/');
6422
6423 if (sname)
6424 *sname++ = '\0';
6425 else {
6426 sname = pname;
6427 pname = NULL;
6428 }
6429
6430 if (pname) {
6431 px = findproxy(pname, PR_CAP_BE);
6432 if (!px) {
6433 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6434 proxy_type_str(curproxy), curproxy->id,
6435 newsrv->id, pname);
6436 cfgerr++;
6437 goto next_srv;
6438 }
6439 } else
6440 px = curproxy;
6441
6442 srv = findserver(px, sname);
6443 if (!srv) {
6444 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6445 proxy_type_str(curproxy), curproxy->id,
6446 newsrv->id, sname);
6447 cfgerr++;
6448 goto next_srv;
6449 }
6450
6451 if (!(srv->state & SRV_CHECKED)) {
6452 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6453 "tracking as it does not have checks enabled.\n",
6454 proxy_type_str(curproxy), curproxy->id,
6455 newsrv->id, px->id, srv->id);
6456 cfgerr++;
6457 goto next_srv;
6458 }
6459
6460 if (curproxy != px &&
6461 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6462 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6463 "tracking: disable-on-404 option inconsistency.\n",
6464 proxy_type_str(curproxy), curproxy->id,
6465 newsrv->id, px->id, srv->id);
6466 cfgerr++;
6467 goto next_srv;
6468 }
6469
6470 /* if the other server is forced disabled, we have to do the same here */
6471 if (srv->state & SRV_MAINTAIN) {
6472 newsrv->state |= SRV_MAINTAIN;
6473 newsrv->state &= ~SRV_RUNNING;
6474 newsrv->health = 0;
6475 }
6476
6477 newsrv->track = srv;
6478 newsrv->tracknext = srv->tracknext;
6479 srv->tracknext = newsrv;
6480
6481 free(newsrv->trackit);
6482 newsrv->trackit = NULL;
6483 }
6484 next_srv:
6485 newsrv = newsrv->next;
6486 }
6487
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006488 /* We have to initialize the server lookup mechanism depending
6489 * on what LB algorithm was choosen.
6490 */
6491
6492 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6493 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6494 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006495 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6496 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6497 init_server_map(curproxy);
6498 } else {
6499 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6500 fwrr_init_server_groups(curproxy);
6501 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006502 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006503
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006504 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006505 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6506 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6507 fwlc_init_server_tree(curproxy);
6508 } else {
6509 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6510 fas_init_server_tree(curproxy);
6511 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006512 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006513
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006514 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006515 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6516 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6517 chash_init_server_tree(curproxy);
6518 } else {
6519 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6520 init_server_map(curproxy);
6521 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006522 break;
6523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524
6525 if (curproxy->options & PR_O_LOGASAP)
6526 curproxy->to_log &= ~LW_BYTES;
6527
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006528 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006529 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006530 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6531 proxy_type_str(curproxy), curproxy->id);
6532 err_code |= ERR_WARN;
6533 }
6534
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006535 if (curproxy->mode != PR_MODE_HTTP) {
6536 int optnum;
6537
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006538 if (curproxy->uri_auth) {
6539 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6540 proxy_type_str(curproxy), curproxy->id);
6541 err_code |= ERR_WARN;
6542 curproxy->uri_auth = NULL;
6543 }
6544
Willy Tarreau87cf5142011-08-19 22:57:24 +02006545 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006546 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6547 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6548 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006549 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006550 }
6551
6552 if (curproxy->options & PR_O_ORGTO) {
6553 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6554 "originalto", proxy_type_str(curproxy), curproxy->id);
6555 err_code |= ERR_WARN;
6556 curproxy->options &= ~PR_O_ORGTO;
6557 }
6558
6559 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6560 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6561 (curproxy->cap & cfg_opts[optnum].cap) &&
6562 (curproxy->options & cfg_opts[optnum].val)) {
6563 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6564 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6565 err_code |= ERR_WARN;
6566 curproxy->options &= ~cfg_opts[optnum].val;
6567 }
6568 }
6569
6570 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6571 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6572 (curproxy->cap & cfg_opts2[optnum].cap) &&
6573 (curproxy->options2 & cfg_opts2[optnum].val)) {
6574 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6575 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6576 err_code |= ERR_WARN;
6577 curproxy->options2 &= ~cfg_opts2[optnum].val;
6578 }
6579 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006580
Willy Tarreauefa5f512010-03-30 20:13:29 +02006581#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006582 if (curproxy->bind_hdr_occ) {
6583 curproxy->bind_hdr_occ = 0;
6584 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6585 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6586 err_code |= ERR_WARN;
6587 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006588#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006589 }
6590
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006592 * ensure that we're not cross-dressing a TCP server into HTTP.
6593 */
6594 newsrv = curproxy->srv;
6595 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006596 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006597 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006599 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006600 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006601
Willy Tarreau0cec3312011-10-31 13:49:26 +01006602 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6603 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6604 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6605 err_code |= ERR_WARN;
6606 }
6607
Willy Tarreauefa5f512010-03-30 20:13:29 +02006608#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006609 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6610 newsrv->bind_hdr_occ = 0;
6611 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6612 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6613 err_code |= ERR_WARN;
6614 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006615#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006616 newsrv = newsrv->next;
6617 }
6618
Willy Tarreauc1a21672009-08-16 22:37:44 +02006619 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006620 if (!curproxy->accept)
6621 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006622
Willy Tarreauc1a21672009-08-16 22:37:44 +02006623 if (curproxy->tcp_req.inspect_delay ||
6624 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006625 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006626
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006627 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006628 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006629 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006630 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006631
6632 /* both TCP and HTTP must check switching rules */
6633 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6634 }
6635
6636 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006637 if (curproxy->tcp_req.inspect_delay ||
6638 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6639 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6640
Emeric Brun97679e72010-09-23 17:56:44 +02006641 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6642 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6643
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006644 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006645 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006646 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006647 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006648
6649 /* If the backend does requires RDP cookie persistence, we have to
6650 * enable the corresponding analyser.
6651 */
6652 if (curproxy->options2 & PR_O2_RDPC_PRST)
6653 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6654 }
6655
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006656 /* Configure SSL for each bind line.
6657 * Note: if configuration fails at some point, the ->ctx member
6658 * remains NULL so that listeners can later detach.
6659 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006660 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6661 if (!bind_conf->is_ssl)
6662 continue;
6663#ifdef USE_OPENSSL
6664 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006665 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006666 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006667 cfgerr++;
6668 continue;
6669 }
6670
Emeric Brun4b3091e2012-09-24 15:48:52 +02006671 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006672 Alert("Unable to allocate SSL session cache.\n");
6673 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006674 continue;
6675 }
6676
Emeric Brunfc0421f2012-09-07 17:30:07 +02006677 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006678 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006679#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006680 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006681
Willy Tarreaue6b98942007-10-29 01:09:36 +01006682 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006683 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006684 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006685 if (!listener->luid) {
6686 /* listener ID not set, use automatic numbering with first
6687 * spare entry starting with next_luid.
6688 */
6689 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6690 listener->conf.id.key = listener->luid = next_id;
6691 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006692 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006693 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006694
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006695 /* enable separate counters */
6696 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6697 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006698 if (!listener->name)
6699 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006700 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006701
Willy Tarreaue6b98942007-10-29 01:09:36 +01006702 if (curproxy->options & PR_O_TCP_NOLING)
6703 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006704 if (!listener->maxconn)
6705 listener->maxconn = curproxy->maxconn;
6706 if (!listener->backlog)
6707 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006708 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006709 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006710 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006711 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006712
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006713 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6714 listener->options |= LI_O_TCP_RULES;
6715
Willy Tarreaude3041d2010-05-31 10:56:17 +02006716 if (curproxy->mon_mask.s_addr)
6717 listener->options |= LI_O_CHK_MONNET;
6718
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006719 /* smart accept mode is automatic in HTTP mode */
6720 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006721 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006722 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6723 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006724 }
6725
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006726 /* Release unused SSL configs */
6727 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6728 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006729 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006730#ifdef USE_OPENSSL
6731 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006732 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006733 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006734 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006735 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006736#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006737 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006738
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006739 /* Check multi-process mode compatibility for the current proxy */
6740 if (global.nbproc > 1) {
6741 int nbproc = 0;
6742 if (curproxy->bind_proc) {
6743 int proc;
6744 for (proc = 0; proc < global.nbproc; proc++) {
6745 if (curproxy->bind_proc & (1 << proc)) {
6746 nbproc++;
6747 }
6748 }
6749 } else {
6750 nbproc = global.nbproc;
6751 }
6752 if (curproxy->table.peers.name) {
6753 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6754 curproxy->id);
6755 cfgerr++;
6756 }
6757 if (nbproc > 1) {
6758 if (curproxy->uri_auth) {
6759 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6760 curproxy->id);
6761 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6762 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6763 curproxy->id);
6764 }
6765 }
6766 if (curproxy->appsession_name) {
6767 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6768 curproxy->id);
6769 }
6770 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6771 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6772 curproxy->id);
6773 }
6774 }
6775 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006776
6777 /* create the task associated with the proxy */
6778 curproxy->task = task_new();
6779 if (curproxy->task) {
6780 curproxy->task->context = curproxy;
6781 curproxy->task->process = manage_proxy;
6782 /* no need to queue, it will be done automatically if some
6783 * listener gets limited.
6784 */
6785 curproxy->task->expire = TICK_ETERNITY;
6786 } else {
6787 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6788 curproxy->id);
6789 cfgerr++;
6790 }
6791
Willy Tarreaubaaee002006-06-26 02:48:02 +02006792 curproxy = curproxy->next;
6793 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006794
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006795 /* Check multi-process mode compatibility */
6796 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006797 if (global.stats_fe && !global.stats_fe->bind_proc) {
6798 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 +01006799 }
6800 }
6801
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006802 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6803 struct auth_users *curuser;
6804 int g;
6805
6806 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6807 unsigned int group_mask = 0;
6808 char *group = NULL;
6809
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006810 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006811 continue;
6812
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006813 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006814
6815 for (g = 0; g < curuserlist->grpcnt; g++)
6816 if (!strcmp(curuserlist->groups[g], group))
6817 break;
6818
6819 if (g == curuserlist->grpcnt) {
6820 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6821 curuserlist->name, group, curuser->user);
6822 err_code |= ERR_ALERT | ERR_FATAL;
6823 goto out;
6824 }
6825
6826 group_mask |= (1 << g);
6827 }
6828
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006829 free(curuser->u.groups);
6830 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006831 }
6832
6833 for (g = 0; g < curuserlist->grpcnt; g++) {
6834 char *user = NULL;
6835
6836 if (!curuserlist->groupusers[g])
6837 continue;
6838
6839 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6840 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6841 if (!strcmp(curuser->user, user))
6842 break;
6843
6844 if (!curuser) {
6845 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6846 curuserlist->name, user, curuserlist->groups[g]);
6847 err_code |= ERR_ALERT | ERR_FATAL;
6848 goto out;
6849 }
6850
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006851 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 }
6853
6854 free(curuserlist->groupusers[g]);
6855 }
6856
6857 free(curuserlist->groupusers);
6858
6859#ifdef DEBUG_AUTH
6860 for (g = 0; g < curuserlist->grpcnt; g++) {
6861 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6862
6863 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006864 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006865 fprintf(stderr, " %s", curuser->user);
6866 }
6867
6868 fprintf(stderr, "\n");
6869 }
6870#endif
6871
Willy Tarreaufbb78422011-06-05 15:38:35 +02006872 }
6873
6874 /* automatically compute fullconn if not set. We must not do it in the
6875 * loop above because cross-references are not yet fully resolved.
6876 */
6877 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6878 /* If <fullconn> is not set, let's set it to 10% of the sum of
6879 * the possible incoming frontend's maxconns.
6880 */
6881 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6882 struct proxy *fe;
6883 int total = 0;
6884
6885 /* sum up the number of maxconns of frontends which
6886 * reference this backend at least once or which are
6887 * the same one ('listen').
6888 */
6889 for (fe = proxy; fe; fe = fe->next) {
6890 struct switching_rule *rule;
6891 struct hdr_exp *exp;
6892 int found = 0;
6893
6894 if (!(fe->cap & PR_CAP_FE))
6895 continue;
6896
6897 if (fe == curproxy) /* we're on a "listen" instance */
6898 found = 1;
6899
6900 if (fe->defbe.be == curproxy) /* "default_backend" */
6901 found = 1;
6902
6903 /* check if a "use_backend" rule matches */
6904 if (!found) {
6905 list_for_each_entry(rule, &fe->switching_rules, list) {
6906 if (rule->be.backend == curproxy) {
6907 found = 1;
6908 break;
6909 }
6910 }
6911 }
6912
6913 /* check if a "reqsetbe" rule matches */
6914 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6915 if (exp->action == ACT_SETBE &&
6916 (struct proxy *)exp->replace == curproxy) {
6917 found = 1;
6918 break;
6919 }
6920 }
6921
6922 /* now we've checked all possible ways to reference a backend
6923 * from a frontend.
6924 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006925 if (!found)
6926 continue;
6927 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006928 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006929 /* we have the sum of the maxconns in <total>. We only
6930 * keep 10% of that sum to set the default fullconn, with
6931 * a hard minimum of 1 (to avoid a divide by zero).
6932 */
6933 curproxy->fullconn = (total + 9) / 10;
6934 if (!curproxy->fullconn)
6935 curproxy->fullconn = 1;
6936 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006937 }
6938
Willy Tarreau056f5682010-06-06 15:51:11 +02006939 /* initialize stick-tables on backend capable proxies. This must not
6940 * be done earlier because the data size may be discovered while parsing
6941 * other proxies.
6942 */
6943 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006944 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006945
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006946 /*
6947 * Recount currently required checks.
6948 */
6949
6950 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6951 int optnum;
6952
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006953 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6954 if (curproxy->options & cfg_opts[optnum].val)
6955 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006956
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006957 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6958 if (curproxy->options2 & cfg_opts2[optnum].val)
6959 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006960 }
6961
Willy Tarreau122541c2011-09-07 21:24:49 +02006962 if (peers) {
6963 struct peers *curpeers = peers, **last;
6964 struct peer *p, *pb;
6965
6966 /* Remove all peers sections which don't have a valid listener.
6967 * This can happen when a peers section is never referenced and
6968 * does not contain a local peer.
6969 */
6970 last = &peers;
6971 while (*last) {
6972 curpeers = *last;
6973 if (curpeers->peers_fe) {
6974 last = &curpeers->next;
6975 continue;
6976 }
6977
6978 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6979 curpeers->id, localpeer);
6980
6981 p = curpeers->remote;
6982 while (p) {
6983 pb = p->next;
6984 free(p->id);
6985 free(p);
6986 p = pb;
6987 }
6988
6989 /* Destroy and unlink this curpeers section.
6990 * Note: curpeers is backed up into *last.
6991 */
6992 free(curpeers->id);
6993 curpeers = curpeers->next;
6994 free(*last);
6995 *last = curpeers;
6996 }
6997 }
6998
Willy Tarreauac1932d2011-10-24 19:14:41 +02006999 if (!global.tune.max_http_hdr)
7000 global.tune.max_http_hdr = MAX_HTTP_HDR;
7001
Willy Tarreau34eb6712011-10-24 18:15:04 +02007002 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007003 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007004 MEM_F_SHARED);
7005
Willy Tarreaubb925012009-07-23 13:36:36 +02007006 if (cfgerr > 0)
7007 err_code |= ERR_ALERT | ERR_FATAL;
7008 out:
7009 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007010}
7011
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007012/*
7013 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7014 * parsing sessions.
7015 */
7016void cfg_register_keywords(struct cfg_kw_list *kwl)
7017{
7018 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7019}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007020
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007021/*
7022 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7023 */
7024void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7025{
7026 LIST_DEL(&kwl->list);
7027 LIST_INIT(&kwl->list);
7028}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029
7030/*
7031 * Local variables:
7032 * c-indent-level: 8
7033 * c-basic-offset: 8
7034 * End:
7035 */