blob: d5ada1dcfff4d63ee1ce6c40b3fad8edcde1748d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020043#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020045#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020054#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020056#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020057#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020059#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010060#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010061#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020062#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020063#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010065#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010068#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069
Emeric Brunfc0421f2012-09-07 17:30:07 +020070#ifdef USE_OPENSSL
71#include <types/ssl_sock.h>
72#include <proto/ssl_sock.h>
73#include <proto/shctx.h>
74#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020075
Willy Tarreauf3c69202006-07-09 16:42:34 +020076/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
77 * ssl-hello-chk option to ensure that the remote server speaks SSL.
78 *
79 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
80 */
81const char sslv3_client_hello_pkt[] = {
82 "\x16" /* ContentType : 0x16 = Hanshake */
83 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
84 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
85 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
86 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
87 "\x03\x00" /* Hello Version : 0x0300 = v3 */
88 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
89 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
90 "\x00" /* Session ID length : empty (no session ID) */
91 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
92 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
93 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
94 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
95 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
96 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
97 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
98 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
99 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
100 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
101 "\x00\x38" "\x00\x39" "\x00\x3A"
102 "\x01" /* Compression Length : 0x01 = 1 byte for types */
103 "\x00" /* Compression Type : 0x00 = NULL compression */
104};
105
Willy Tarreau3842f002009-06-14 11:39:52 +0200106/* various keyword modifiers */
107enum kw_mod {
108 KWM_STD = 0, /* normal */
109 KWM_NO, /* "no" prefixed before the keyword */
110 KWM_DEF, /* "default" prefixed before the keyword */
111};
112
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100114struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115 const char *name;
116 unsigned int val;
117 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100118 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100119 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100120};
121
122/* proxy->options */
123static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100124{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100125 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
126 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
127 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
129 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
130 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
131 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
135 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
136 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
137 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
138 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
139 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
140 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100141#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100143#else
144 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100145#endif
146
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148};
149
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150/* proxy->options2 */
151static const struct cfg_opt cfg_opts2[] =
152{
153#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
155 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100157#else
158 { "splice-request", 0, 0, 0, 0 },
159 { "splice-response", 0, 0, 0, 0 },
160 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100161#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
163 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
164 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
165 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
166 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
167 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
168 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
170 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400171 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100172 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200173 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200174 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100175 { NULL, 0, 0, 0 }
176};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177
Willy Tarreau6daf3432008-01-22 16:44:08 +0100178static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
180int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100181int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200183/* List head of all known configuration keywords */
184static struct cfg_kw_list cfg_keywords = {
185 .list = LIST_HEAD_INIT(cfg_keywords.list)
186};
187
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188/*
189 * converts <str> to a list of listeners which are dynamically allocated.
190 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
191 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
192 * - <port> is a numerical port from 1 to 65535 ;
193 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
194 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200195 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
196 * not NULL, it must be a valid pointer to either NULL or a freeable area that
197 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200199int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200{
201 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100202 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 int port, end;
204
205 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 while (next && *next) {
208 struct sockaddr_storage ss;
209
210 str = next;
211 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100212 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 *next++ = 0;
214 }
215
Emeric Bruned760922010-10-22 17:59:25 +0200216 if (*str == '/') {
217 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
218 /* so compute max path */
219 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
220 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Emeric Bruned760922010-10-22 17:59:25 +0200222 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200224 goto fail;
225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200228 ss.ss_family = AF_UNIX;
229 if (global.unix_bind.prefix) {
230 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
231 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232 }
Emeric Bruned760922010-10-22 17:59:25 +0200233 else {
234 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
235 }
236 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 }
238 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100241 ss2 = str2sa_range(str, &port, &end);
242 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200243 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 /* OK the address looks correct */
253 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Emeric Bruned760922010-10-22 17:59:25 +0200255 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200256 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
265
266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau4348fad2012-09-20 16:48:07 +0200268 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
269 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
270 l->frontend = curproxy;
271 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
273 l->fd = -1;
274 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200275 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100276 l->state = LI_INIT;
277
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100278 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200279 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100280 tcpv4_add_listener(l);
281 }
Emeric Bruned760922010-10-22 17:59:25 +0200282 else if (ss.ss_family == AF_INET6) {
283 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
284 tcpv6_add_listener(l);
285 }
286 else {
Emeric Bruned760922010-10-22 17:59:25 +0200287 uxst_add_listener(l);
288 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200290 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100291 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 } /* end for(port) */
293 } /* end while(next) */
294 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200295 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 fail:
297 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299}
300
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301/*
302 * Sends a warning if proxy <proxy> does not have at least one of the
303 * capabilities in <cap>. An optionnal <hint> may be added at the end
304 * of the warning to help the user. Returns 1 if a warning was emitted
305 * or 0 if the condition is valid.
306 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100307int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100308{
309 char *msg;
310
311 switch (cap) {
312 case PR_CAP_BE: msg = "no backend"; break;
313 case PR_CAP_FE: msg = "no frontend"; break;
314 case PR_CAP_RS: msg = "no ruleset"; break;
315 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
316 default: msg = "not enough"; break;
317 }
318
319 if (!(proxy->cap & cap)) {
320 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100321 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100322 return 1;
323 }
324 return 0;
325}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326
Willy Tarreau61d18892009-03-31 10:49:21 +0200327/* Report a warning if a rule is placed after a 'block' rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100330int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200331{
332 if (!LIST_ISEMPTY(&proxy->block_cond)) {
333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a reqrewrite rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100343int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200344{
345 if (proxy->req_exp) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a reqadd rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100356int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200357{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100358 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* Report a warning if a rule is placed after a redirect rule.
367 * Return 1 if the warning has been emitted, otherwise 0.
368 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
372 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
373 file, line, arg);
374 return 1;
375 }
376 return 0;
377}
378
379/* Report a warning if a rule is placed after a 'use_backend' rule.
380 * Return 1 if the warning has been emitted, otherwise 0.
381 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
385 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
386 file, line, arg);
387 return 1;
388 }
389 return 0;
390}
391
392/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
396 warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
405 warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
409/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
412 return warnif_rule_after_redirect(proxy, file, line, arg) ||
413 warnif_rule_after_use_backend(proxy, file, line, arg);
414}
415
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100416/* Report it if a request ACL condition uses some response-only parameters. It
417 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
418 * Note that <cond> may be NULL and then will be ignored.
419 */
420static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
421{
422 struct acl *acl;
423
424 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
425 return 0;
426
427 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
428 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
429 file, line, acl ? acl->name : "(unknown)");
430 return ERR_WARN;
431}
432
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100433/* Report it if a request ACL condition uses some request-only volatile parameters.
434 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
435 * Note that <cond> may be NULL and then will be ignored.
436 */
437static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
438{
439 struct acl *acl;
440
441 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
442 return 0;
443
444 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
445 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
446 file, line, acl ? acl->name : "(unknown)");
447 return ERR_WARN;
448}
449
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200452 * parse a line in a <global> section. Returns the error code, 0 if OK, or
453 * any combination of :
454 * - ERR_ABORT: must abort ASAP
455 * - ERR_FATAL: we can continue parsing but not start the service
456 * - ERR_WARN: a warning has been emitted
457 * - ERR_ALERT: an alert has been emitted
458 * Only the two first ones can stop processing, the two others are just
459 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200461int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462{
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200464 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465
466 if (!strcmp(args[0], "global")) { /* new section */
467 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200470 else if (!strcmp(args[0], "ca-base")) {
471#ifdef USE_OPENSSL
472 if (global.ca_base != NULL) {
473 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
474 err_code |= ERR_ALERT;
475 goto out;
476 }
477 if (*(args[1]) == 0) {
478 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
479 err_code |= ERR_ALERT | ERR_FATAL;
480 goto out;
481 }
482 global.ca_base = strdup(args[1]);
483#else
484 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
485 err_code |= ERR_ALERT | ERR_FATAL;
486 goto out;
487#endif
488 }
489 else if (!strcmp(args[0], "crt-base")) {
490#ifdef USE_OPENSSL
491 if (global.crt_base != NULL) {
492 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
493 err_code |= ERR_ALERT;
494 goto out;
495 }
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
500 }
501 global.crt_base = strdup(args[1]);
502#else
503 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
506#endif
507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200508 else if (!strcmp(args[0], "daemon")) {
509 global.mode |= MODE_DAEMON;
510 }
511 else if (!strcmp(args[0], "debug")) {
512 global.mode |= MODE_DEBUG;
513 }
514 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100515 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200516 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100518 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 }
520 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100521 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200523 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100524 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200525 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100526 else if (!strcmp(args[0], "nosplice")) {
527 global.tune.options &= ~GTUNE_USE_SPLICE;
528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200529 else if (!strcmp(args[0], "quiet")) {
530 global.mode |= MODE_QUIET;
531 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 else if (!strcmp(args[0], "tune.maxpollevents")) {
533 if (global.tune.maxpollevents != 0) {
534 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200542 }
543 global.tune.maxpollevents = atol(args[1]);
544 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 else if (!strcmp(args[0], "tune.maxaccept")) {
546 if (global.tune.maxaccept != 0) {
547 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 if (*(args[1]) == 0) {
552 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200553 err_code |= ERR_ALERT | ERR_FATAL;
554 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100555 }
556 global.tune.maxaccept = atol(args[1]);
557 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200558 else if (!strcmp(args[0], "tune.chksize")) {
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.chksize = atol(args[1]);
565 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200566#ifdef USE_OPENSSL
567 else if (!strcmp(args[0], "tune.sslcachesize")) {
568 if (*(args[1]) == 0) {
569 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
570 err_code |= ERR_ALERT | ERR_FATAL;
571 goto out;
572 }
573 global.tune.sslcachesize = atol(args[1]);
574 }
575#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200576 else if (!strcmp(args[0], "tune.bufsize")) {
577 if (*(args[1]) == 0) {
578 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT | ERR_FATAL;
580 goto out;
581 }
582 global.tune.bufsize = atol(args[1]);
583 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
584 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100585 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200586 }
587 else if (!strcmp(args[0], "tune.maxrewrite")) {
588 if (*(args[1]) == 0) {
589 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT | ERR_FATAL;
591 goto out;
592 }
593 global.tune.maxrewrite = atol(args[1]);
594 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
595 global.tune.maxrewrite = global.tune.bufsize / 2;
596 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100597 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
598 if (global.tune.client_rcvbuf != 0) {
599 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
600 err_code |= ERR_ALERT;
601 goto out;
602 }
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.client_rcvbuf = atol(args[1]);
609 }
610 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
611 if (global.tune.server_rcvbuf != 0) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.server_rcvbuf = atol(args[1]);
622 }
623 else if (!strcmp(args[0], "tune.sndbuf.client")) {
624 if (global.tune.client_sndbuf != 0) {
625 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
626 err_code |= ERR_ALERT;
627 goto out;
628 }
629 if (*(args[1]) == 0) {
630 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
631 err_code |= ERR_ALERT | ERR_FATAL;
632 goto out;
633 }
634 global.tune.client_sndbuf = atol(args[1]);
635 }
636 else if (!strcmp(args[0], "tune.sndbuf.server")) {
637 if (global.tune.server_sndbuf != 0) {
638 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
639 err_code |= ERR_ALERT;
640 goto out;
641 }
642 if (*(args[1]) == 0) {
643 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
644 err_code |= ERR_ALERT | ERR_FATAL;
645 goto out;
646 }
647 global.tune.server_sndbuf = atol(args[1]);
648 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200649 else if (!strcmp(args[0], "tune.pipesize")) {
650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.pipesize = atol(args[1]);
656 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200657 else if (!strcmp(args[0], "tune.http.maxhdr")) {
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
662 }
663 global.tune.max_http_hdr = atol(args[1]);
664 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100665 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
666#ifdef USE_ZLIB
667 if (*args[1]) {
668 global.tune.zlibmemlevel = atoi(args[1]);
669 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
670 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
671 file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675 } else {
676 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
677 file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681#else
682 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
683 err_code |= ERR_ALERT | ERR_FATAL;
684 goto out;
685#endif
686 }
687 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
688#ifdef USE_ZLIB
689 if (*args[1]) {
690 global.tune.zlibwindowsize = atoi(args[1]);
691 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
692 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
693 file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 } else {
698 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
699 file, linenum, args[0]);
700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
702 }
703#else
704 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
707#endif
708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 else if (!strcmp(args[0], "uid")) {
710 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200711 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 }
720 global.uid = atol(args[1]);
721 }
722 else if (!strcmp(args[0], "gid")) {
723 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200724 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200732 }
733 global.gid = atol(args[1]);
734 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200735 /* user/group name handling */
736 else if (!strcmp(args[0], "user")) {
737 struct passwd *ha_user;
738 if (global.uid != 0) {
739 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200742 }
743 errno = 0;
744 ha_user = getpwnam(args[1]);
745 if (ha_user != NULL) {
746 global.uid = (int)ha_user->pw_uid;
747 }
748 else {
749 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200751 }
752 }
753 else if (!strcmp(args[0], "group")) {
754 struct group *ha_group;
755 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200756 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT;
758 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 }
760 errno = 0;
761 ha_group = getgrnam(args[1]);
762 if (ha_group != NULL) {
763 global.gid = (int)ha_group->gr_gid;
764 }
765 else {
766 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200767 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200768 }
769 }
770 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "nbproc")) {
772 if (global.nbproc != 0) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.nbproc = atol(args[1]);
783 }
784 else if (!strcmp(args[0], "maxconn")) {
785 if (global.maxconn != 0) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 }
795 global.maxconn = atol(args[1]);
796#ifdef SYSTEM_MAXCONN
797 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
798 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
799 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 }
802#endif /* SYSTEM_MAXCONN */
803 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200804 else if (!strcmp(args[0], "maxsslconn")) {
805#ifdef USE_OPENSSL
806 if (*(args[1]) == 0) {
807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
808 err_code |= ERR_ALERT | ERR_FATAL;
809 goto out;
810 }
811 global.maxsslconn = atol(args[1]);
812#else
Emeric Brun0914df82012-10-02 18:45:42 +0200813 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200816#endif
817 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200818 else if (!strcmp(args[0], "maxconnrate")) {
819 if (global.cps_lim != 0) {
820 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
821 err_code |= ERR_ALERT;
822 goto out;
823 }
824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
828 }
829 global.cps_lim = atol(args[1]);
830 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100831 else if (!strcmp(args[0], "maxpipes")) {
832 if (global.maxpipes != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT;
835 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100841 }
842 global.maxpipes = atol(args[1]);
843 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100844 else if (!strcmp(args[0], "maxzlibmem")) {
845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
849 }
850 global.maxzlibmem = atol(args[1]);
851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200852 else if (!strcmp(args[0], "ulimit-n")) {
853 if (global.rlimit_nofile != 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 Tarreaubaaee002006-06-26 02:48:02 +0200857 }
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 Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 global.rlimit_nofile = atol(args[1]);
864 }
865 else if (!strcmp(args[0], "chroot")) {
866 if (global.chroot != NULL) {
867 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870 }
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875 }
876 global.chroot = strdup(args[1]);
877 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200878 else if (!strcmp(args[0], "description")) {
879 int i, len=0;
880 char *d;
881
882 if (!*args[1]) {
883 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
884 file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888
889 for(i=1; *args[i]; i++)
890 len += strlen(args[i])+1;
891
892 if (global.desc)
893 free(global.desc);
894
895 global.desc = d = (char *)calloc(1, len);
896
897 d += sprintf(d, "%s", args[1]);
898 for(i=2; *args[i]; i++)
899 d += sprintf(d, " %s", args[i]);
900 }
901 else if (!strcmp(args[0], "node")) {
902 int i;
903 char c;
904
905 for (i=0; args[1][i]; i++) {
906 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100907 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
908 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200909 break;
910 }
911
912 if (!i || args[1][i]) {
913 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
914 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
915 file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919
920 if (global.node)
921 free(global.node);
922
923 global.node = strdup(args[1]);
924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 else if (!strcmp(args[0], "pidfile")) {
926 if (global.pidfile != NULL) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200928 err_code |= ERR_ALERT;
929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 global.pidfile = strdup(args[1]);
937 }
Emeric Bruned760922010-10-22 17:59:25 +0200938 else if (!strcmp(args[0], "unix-bind")) {
939 int cur_arg = 1;
940 while (*(args[cur_arg])) {
941 if (!strcmp(args[cur_arg], "prefix")) {
942 if (global.unix_bind.prefix != NULL) {
943 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
944 err_code |= ERR_ALERT;
945 cur_arg += 2;
946 continue;
947 }
948
949 if (*(args[cur_arg+1]) == 0) {
950 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
951 err_code |= ERR_ALERT | ERR_FATAL;
952 goto out;
953 }
954 global.unix_bind.prefix = strdup(args[cur_arg+1]);
955 cur_arg += 2;
956 continue;
957 }
958
959 if (!strcmp(args[cur_arg], "mode")) {
960
961 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
962 cur_arg += 2;
963 continue;
964 }
965
966 if (!strcmp(args[cur_arg], "uid")) {
967
968 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
969 cur_arg += 2;
970 continue;
971 }
972
973 if (!strcmp(args[cur_arg], "gid")) {
974
975 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
976 cur_arg += 2;
977 continue;
978 }
979
980 if (!strcmp(args[cur_arg], "user")) {
981 struct passwd *user;
982
983 user = getpwnam(args[cur_arg + 1]);
984 if (!user) {
985 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
986 file, linenum, args[0], args[cur_arg + 1 ]);
987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
989 }
990
991 global.unix_bind.ux.uid = user->pw_uid;
992 cur_arg += 2;
993 continue;
994 }
995
996 if (!strcmp(args[cur_arg], "group")) {
997 struct group *group;
998
999 group = getgrnam(args[cur_arg + 1]);
1000 if (!group) {
1001 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1002 file, linenum, args[0], args[cur_arg + 1 ]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006
1007 global.unix_bind.ux.gid = group->gr_gid;
1008 cur_arg += 2;
1009 continue;
1010 }
1011
Willy Tarreaub48f9582011-09-05 01:17:06 +02001012 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001013 file, linenum, args[0]);
1014 err_code |= ERR_ALERT | ERR_FATAL;
1015 goto out;
1016 }
1017 }
William Lallemand0f99e342011-10-12 17:50:54 +02001018 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1019 /* delete previous herited or defined syslog servers */
1020 struct logsrv *back;
1021 struct logsrv *tmp;
1022
1023 if (*(args[1]) != 0) {
1024 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028
1029 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1030 LIST_DEL(&tmp->list);
1031 free(tmp);
1032 }
1033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001035 struct logsrv *logsrv;
1036
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 if (*(args[1]) == 0 || *(args[2]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
William Lallemand0f99e342011-10-12 17:50:54 +02001042
1043 logsrv = calloc(1, sizeof(struct logsrv));
1044
1045 logsrv->facility = get_log_facility(args[2]);
1046 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001049 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 }
1051
William Lallemand0f99e342011-10-12 17:50:54 +02001052 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001054 logsrv->level = get_log_level(args[3]);
1055 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001058 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 }
1061
William Lallemand0f99e342011-10-12 17:50:54 +02001062 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001063 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001064 logsrv->minlvl = get_log_level(args[4]);
1065 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001066 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001067 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001068 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001069 }
1070 }
1071
Robert Tsai81ae1952007-12-05 10:47:29 +01001072 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001073 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001074 if (!sk) {
1075 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001076 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001077 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001078 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001079 goto out;
1080 }
William Lallemand0f99e342011-10-12 17:50:54 +02001081 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001082 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001083 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001084 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001085 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001087 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001088 goto out;
1089 }
William Lallemand0f99e342011-10-12 17:50:54 +02001090 logsrv->addr = *sk;
1091 if (!get_host_port(&logsrv->addr))
1092 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094
William Lallemand0f99e342011-10-12 17:50:54 +02001095 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001096 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001097 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1098 char *name;
1099 int len;
1100
1101 if (global.log_send_hostname != NULL) {
1102 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1103 err_code |= ERR_ALERT;
1104 goto out;
1105 }
1106
1107 if (*(args[1]))
1108 name = args[1];
1109 else
1110 name = hostname;
1111
1112 len = strlen(name);
1113
1114 /* We'll add a space after the name to respect the log format */
1115 free(global.log_send_hostname);
1116 global.log_send_hostname = malloc(len + 2);
1117 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1118 }
Kevinm48936af2010-12-22 16:08:21 +00001119 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
1124 }
1125 free(global.log_tag);
1126 global.log_tag = strdup(args[1]);
1127 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001128 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1129 if (global.spread_checks != 0) {
1130 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001131 err_code |= ERR_ALERT;
1132 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001133 }
1134 if (*(args[1]) == 0) {
1135 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001138 }
1139 global.spread_checks = atol(args[1]);
1140 if (global.spread_checks < 0 || global.spread_checks > 50) {
1141 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001146 struct cfg_kw_list *kwl;
1147 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001148 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001149
1150 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1151 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1152 if (kwl->kw[index].section != CFG_GLOBAL)
1153 continue;
1154 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001155 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001156 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001157 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001159 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001160 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001161 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001162 err_code |= ERR_WARN;
1163 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001164 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001165 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001166 }
1167 }
1168 }
1169
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001173
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001175 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177}
1178
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001179void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001181 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 defproxy.mode = PR_MODE_TCP;
1183 defproxy.state = PR_STNEW;
1184 defproxy.maxconn = cfg_maxpconn;
1185 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001186
1187 defproxy.defsrv.inter = DEF_CHKINTR;
1188 defproxy.defsrv.fastinter = 0;
1189 defproxy.defsrv.downinter = 0;
1190 defproxy.defsrv.rise = DEF_RISETIME;
1191 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001192 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001193 defproxy.defsrv.maxqueue = 0;
1194 defproxy.defsrv.minconn = 0;
1195 defproxy.defsrv.maxconn = 0;
1196 defproxy.defsrv.slowstart = 0;
1197 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1198 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1199 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001200}
1201
Willy Tarreauade5ec42010-01-28 19:33:49 +01001202
1203static int create_cond_regex_rule(const char *file, int line,
1204 struct proxy *px, int dir, int action, int flags,
1205 const char *cmd, const char *reg, const char *repl,
1206 const char **cond_start)
1207{
1208 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001209 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001210 const char *err;
1211 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001212 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001213
1214 if (px == &defproxy) {
1215 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto err;
1218 }
1219
1220 if (*reg == 0) {
1221 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1222 err_code |= ERR_ALERT | ERR_FATAL;
1223 goto err;
1224 }
1225
1226 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1227 err_code |= ERR_WARN;
1228
Willy Tarreau5321c422010-01-28 20:35:13 +01001229 if (cond_start &&
1230 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001231 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1232 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1233 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto err;
1236 }
1237 }
1238 else if (cond_start && **cond_start) {
1239 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1240 file, line, cmd, *cond_start);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto err;
1243 }
1244
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001245 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001246 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001247 else
1248 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001249
Willy Tarreauade5ec42010-01-28 19:33:49 +01001250 preg = calloc(1, sizeof(regex_t));
1251 if (!preg) {
1252 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1253 err_code = ERR_ALERT | ERR_FATAL;
1254 goto err;
1255 }
1256
1257 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1258 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1259 err_code = ERR_ALERT | ERR_FATAL;
1260 goto err;
1261 }
1262
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001263 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001264 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001265 if (repl && err) {
1266 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1267 file, line, cmd, *err);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto err;
1270 }
1271
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001272 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001273 err_code |= ERR_WARN;
1274
Willy Tarreauf4068b62012-05-08 17:37:49 +02001275 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001276 return err_code;
1277 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001278 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001279 free(preg);
1280 return err_code;
1281}
1282
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001284 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001285 * Returns the error code, 0 if OK, or any combination of :
1286 * - ERR_ABORT: must abort ASAP
1287 * - ERR_FATAL: we can continue parsing but not start the service
1288 * - ERR_WARN: a warning has been emitted
1289 * - ERR_ALERT: an alert has been emitted
1290 * Only the two first ones can stop processing, the two others are just
1291 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001292 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001293int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1294{
1295 static struct peers *curpeers = NULL;
1296 struct peer *newpeer = NULL;
1297 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001298 struct bind_conf *bind_conf;
1299 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001300 int err_code = 0;
1301
1302 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1303
1304 err = invalid_char(args[1]);
1305 if (err) {
1306 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1307 file, linenum, *err, args[0], args[1]);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 }
1310
1311 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1312 /*
1313 * If there are two proxies with the same name only following
1314 * combinations are allowed:
1315 */
1316 if (strcmp(curpeers->id, args[1]) == 0) {
1317 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1318 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1319 err_code |= ERR_WARN;
1320 }
1321 }
1322
1323 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1325 err_code |= ERR_ALERT | ERR_ABORT;
1326 goto out;
1327 }
1328
1329 curpeers->next = peers;
1330 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001331 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001332 curpeers->conf.line = linenum;
1333 curpeers->last_change = now.tv_sec;
1334 curpeers->id = strdup(args[1]);
1335 }
1336 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1337 char *rport, *raddr;
1338 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001339 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001340 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001341
1342 if (!*args[2]) {
1343 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1344 file, linenum, args[0]);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348
1349 err = invalid_char(args[1]);
1350 if (err) {
1351 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1352 file, linenum, *err, args[1]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356
1357 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1359 err_code |= ERR_ALERT | ERR_ABORT;
1360 goto out;
1361 }
1362
1363 /* the peers are linked backwards first */
1364 curpeers->count++;
1365 newpeer->next = curpeers->remote;
1366 curpeers->remote = newpeer;
1367 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001368 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001369 newpeer->conf.line = linenum;
1370
1371 newpeer->last_change = now.tv_sec;
1372 newpeer->id = strdup(args[1]);
1373
1374 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001375 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001376 if (rport) {
1377 *rport++ = 0;
1378 realport = atol(rport);
1379 }
1380 if (!realport) {
1381 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
1384 }
1385
Willy Tarreaufab5a432011-03-04 15:31:53 +01001386 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001387 free(raddr);
1388 if (!sk) {
1389 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1390 err_code |= ERR_ALERT | ERR_FATAL;
1391 goto out;
1392 }
1393 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001394 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001395 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001396 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001397
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001398 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001399 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1400 file, linenum, newpeer->addr.ss_family, args[2]);
1401 err_code |= ERR_ALERT | ERR_FATAL;
1402 goto out;
1403 }
1404
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001405 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001406
1407 if (strcmp(newpeer->id, localpeer) == 0) {
1408 /* Current is local peer, it define a frontend */
1409 newpeer->local = 1;
1410
1411 if (!curpeers->peers_fe) {
1412 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1413 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1414 err_code |= ERR_ALERT | ERR_ABORT;
1415 goto out;
1416 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001417
Willy Tarreau237250c2011-07-29 01:49:03 +02001418 init_new_proxy(curpeers->peers_fe);
1419 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001420
1421 curpeers->peers_fe->last_change = now.tv_sec;
1422 curpeers->peers_fe->id = strdup(args[1]);
1423 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001424 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001425 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1426 curpeers->peers_fe->timeout.connect = 5000;
1427 curpeers->peers_fe->accept = peer_accept;
1428 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001429
1430 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1431
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001432 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1433 if (err_msg && *err_msg) {
1434 indent_msg(&err_msg, 2);
1435 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1436 }
1437 else
1438 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1439 file, linenum, args[0], args[1], args[2]);
1440 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001441 err_code |= ERR_FATAL;
1442 goto out;
1443 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001444
1445 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1446 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1447 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1448 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1449 l->accept = session_accept;
1450 l->handler = process_session;
1451 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1452 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1453 global.maxsock += l->maxconn;
1454 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001455 }
1456 }
1457 } /* neither "peer" nor "peers" */
1458 else if (*args[0] != 0) {
1459 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
1462 }
1463
1464out:
1465 return err_code;
1466}
1467
1468
Willy Tarreau3842f002009-06-14 11:39:52 +02001469int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470{
1471 static struct proxy *curproxy = NULL;
1472 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001473 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001474 int rc;
1475 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001476 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001477 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001478 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001479 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001480 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
Willy Tarreau977b8e42006-12-29 14:19:17 +01001482 if (!strcmp(args[0], "listen"))
1483 rc = PR_CAP_LISTEN;
1484 else if (!strcmp(args[0], "frontend"))
1485 rc = PR_CAP_FE | PR_CAP_RS;
1486 else if (!strcmp(args[0], "backend"))
1487 rc = PR_CAP_BE | PR_CAP_RS;
1488 else if (!strcmp(args[0], "ruleset"))
1489 rc = PR_CAP_RS;
1490 else
1491 rc = PR_CAP_NONE;
1492
1493 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494 if (!*args[1]) {
1495 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1496 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001498 err_code |= ERR_ALERT | ERR_ABORT;
1499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001501
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001502 err = invalid_char(args[1]);
1503 if (err) {
1504 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1505 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001507 }
1508
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001509 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1510 /*
1511 * If there are two proxies with the same name only following
1512 * combinations are allowed:
1513 *
1514 * listen backend frontend ruleset
1515 * listen - - - -
1516 * backend - - OK -
1517 * frontend - OK - -
1518 * ruleset - - - -
1519 */
1520
1521 if (!strcmp(curproxy->id, args[1]) &&
1522 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1523 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001524 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1525 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1526 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001527 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001528 }
1529 }
1530
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1532 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001533 err_code |= ERR_ALERT | ERR_ABORT;
1534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001536
Willy Tarreau97cb7802010-01-03 20:23:58 +01001537 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 curproxy->next = proxy;
1539 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001540 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001541 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001542 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001544 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545
1546 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001547 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001548 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001549 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001550
Willy Tarreau4348fad2012-09-20 16:48:07 +02001551 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1552
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001553 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1554 if (err_msg && *err_msg) {
1555 indent_msg(&err_msg, 2);
1556 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1557 }
1558 else
1559 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1560 file, linenum, args[0], args[1], args[2]);
1561 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001562 err_code |= ERR_FATAL;
1563 goto out;
1564 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001565
Willy Tarreau4348fad2012-09-20 16:48:07 +02001566 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001567 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 }
1570
1571 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001572 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001573 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001574
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001577 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001578 curproxy->no_options = defproxy.no_options;
1579 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001580 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001581 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001582 curproxy->except_net = defproxy.except_net;
1583 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001584 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001585 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001587 if (defproxy.fwdfor_hdr_len) {
1588 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1589 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1590 }
1591
Willy Tarreaub86db342009-11-30 11:50:16 +01001592 if (defproxy.orgto_hdr_len) {
1593 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1594 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1595 }
1596
Mark Lamourinec2247f02012-01-04 13:02:01 -05001597 if (defproxy.server_id_hdr_len) {
1598 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1599 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1600 }
1601
Willy Tarreau977b8e42006-12-29 14:19:17 +01001602 if (curproxy->cap & PR_CAP_FE) {
1603 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001604 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001605 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001606
1607 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001608 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1609 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610
1611 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613
Willy Tarreau977b8e42006-12-29 14:19:17 +01001614 if (curproxy->cap & PR_CAP_BE) {
1615 curproxy->fullconn = defproxy.fullconn;
1616 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001618 if (defproxy.check_req) {
1619 curproxy->check_req = calloc(1, defproxy.check_len);
1620 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1621 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001622 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001624 if (defproxy.expect_str) {
1625 curproxy->expect_str = strdup(defproxy.expect_str);
1626 if (defproxy.expect_regex) {
1627 /* note: this regex is known to be valid */
1628 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1629 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1630 }
1631 }
1632
Willy Tarreau67402132012-05-31 20:40:20 +02001633 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001634 if (defproxy.cookie_name)
1635 curproxy->cookie_name = strdup(defproxy.cookie_name);
1636 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001637 if (defproxy.cookie_domain)
1638 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001639
Willy Tarreau31936852010-10-06 16:59:56 +02001640 if (defproxy.cookie_maxidle)
1641 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1642
1643 if (defproxy.cookie_maxlife)
1644 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1645
Emeric Brun647caf12009-06-30 17:57:00 +02001646 if (defproxy.rdp_cookie_name)
1647 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1648 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1649
Willy Tarreau01732802007-11-01 22:48:15 +01001650 if (defproxy.url_param_name)
1651 curproxy->url_param_name = strdup(defproxy.url_param_name);
1652 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001653
Benoitaffb4812009-03-25 13:02:10 +01001654 if (defproxy.hh_name)
1655 curproxy->hh_name = strdup(defproxy.hh_name);
1656 curproxy->hh_len = defproxy.hh_len;
1657 curproxy->hh_match_domain = defproxy.hh_match_domain;
1658
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001659 if (defproxy.iface_name)
1660 curproxy->iface_name = strdup(defproxy.iface_name);
1661 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001664 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001665 if (defproxy.capture_name)
1666 curproxy->capture_name = strdup(defproxy.capture_name);
1667 curproxy->capture_namelen = defproxy.capture_namelen;
1668 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670
Willy Tarreau977b8e42006-12-29 14:19:17 +01001671 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001672 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001673 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001674 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001675 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001676 curproxy->uri_auth = defproxy.uri_auth;
1677 curproxy->mon_net = defproxy.mon_net;
1678 curproxy->mon_mask = defproxy.mon_mask;
1679 if (defproxy.monitor_uri)
1680 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1681 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001682 if (defproxy.defbe.name)
1683 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001684
1685 /* get either a pointer to the logformat string or a copy of it */
1686 curproxy->logformat_string = defproxy.logformat_string;
1687 if (curproxy->logformat_string &&
1688 curproxy->logformat_string != default_http_log_format &&
1689 curproxy->logformat_string != default_tcp_log_format &&
1690 curproxy->logformat_string != clf_http_log_format)
1691 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001692 }
1693
1694 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001695 curproxy->timeout.connect = defproxy.timeout.connect;
1696 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001697 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001698 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001699 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001700 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001701 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001702 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 curproxy->source_addr = defproxy.source_addr;
1704 }
1705
Willy Tarreaubaaee002006-06-26 02:48:02 +02001706 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001707
1708 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001709 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001710 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001711 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001712 LIST_INIT(&node->list);
1713 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1714 }
1715
Willy Tarreau196729e2012-05-31 19:30:26 +02001716 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1717 if (curproxy->uniqueid_format_string)
1718 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001719
1720 /* copy default header unique id */
1721 if (defproxy.header_unique_id)
1722 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1723
William Lallemand82fe75c2012-10-23 10:25:10 +02001724 /* default compression options */
1725 if (defproxy.comp != NULL) {
1726 curproxy->comp = calloc(1, sizeof(struct comp));
1727 curproxy->comp->algos = defproxy.comp->algos;
1728 curproxy->comp->types = defproxy.comp->types;
1729 }
1730
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001732 curproxy->conf.used_listener_id = EB_ROOT;
1733 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001734
Willy Tarreau93893792009-07-23 13:19:11 +02001735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 }
1737 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1738 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001739 /* FIXME-20070101: we should do this too at the end of the
1740 * config parsing to free all default values.
1741 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001742 free(defproxy.check_req);
1743 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001744 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001745 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001746 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001747 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001748 free(defproxy.capture_name);
1749 free(defproxy.monitor_uri);
1750 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001751 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001752 free(defproxy.fwdfor_hdr_name);
1753 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001754 free(defproxy.orgto_hdr_name);
1755 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001756 free(defproxy.server_id_hdr_name);
1757 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001758 free(defproxy.expect_str);
1759 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001760
Willy Tarreau39b06652012-06-01 10:58:06 +02001761 if (defproxy.logformat_string != default_http_log_format &&
1762 defproxy.logformat_string != default_tcp_log_format &&
1763 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001764 free(defproxy.logformat_string);
1765
1766 free(defproxy.uniqueid_format_string);
1767
Willy Tarreaua534fea2008-08-03 12:19:50 +02001768 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001769 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001770
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 /* we cannot free uri_auth because it might already be used */
1772 init_default_instance();
1773 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001774 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 }
1777 else if (curproxy == NULL) {
1778 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001781 }
1782
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783
1784 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001786 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001787 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001788 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 if (curproxy == &defproxy) {
1791 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797
Emeric Bruned760922010-10-22 17:59:25 +02001798 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001799 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001804
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001805 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001806 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001807
1808 /* NOTE: the following line might create several listeners if there
1809 * are comma-separated IPs or port ranges. So all further processing
1810 * will have to be applied to all listeners created after last_listen.
1811 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001812 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1813 if (err_msg && *err_msg) {
1814 indent_msg(&err_msg, 2);
1815 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1816 }
1817 else
1818 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1819 file, linenum, args[0], args[1]);
1820 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001824
Willy Tarreau4348fad2012-09-20 16:48:07 +02001825 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1826 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001827 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001828 }
1829
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001830 cur_arg = 2;
1831 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001832 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001833 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001834 char *err;
1835
Willy Tarreau26982662012-09-12 23:17:10 +02001836 kw = bind_find_kw(args[cur_arg]);
1837 if (kw) {
1838 char *err = NULL;
1839 int code;
1840
1841 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001842 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1843 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001844 cur_arg += 1 + kw->skip ;
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 }
1848
Willy Tarreau4348fad2012-09-20 16:48:07 +02001849 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001850 err_code |= code;
1851
1852 if (code) {
1853 if (err && *err) {
1854 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001855 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001856 }
1857 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001858 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1859 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001860 if (code & ERR_FATAL) {
1861 free(err);
1862 cur_arg += 1 + kw->skip;
1863 goto out;
1864 }
1865 }
1866 free(err);
1867 cur_arg += 1 + kw->skip;
1868 continue;
1869 }
1870
Willy Tarreau8638f482012-09-18 18:01:17 +02001871 err = NULL;
1872 if (!bind_dumped) {
1873 bind_dump_kws(&err);
1874 indent_msg(&err, 4);
1875 bind_dumped = 1;
1876 }
1877
1878 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1879 file, linenum, args[0], args[1], args[cur_arg],
1880 err ? " Registered keywords :" : "", err ? err : "");
1881 free(err);
1882
Willy Tarreau93893792009-07-23 13:19:11 +02001883 err_code |= ERR_ALERT | ERR_FATAL;
1884 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001885 }
Willy Tarreau93893792009-07-23 13:19:11 +02001886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 }
1888 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1889 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1890 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1891 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 /* flush useless bits */
1899 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001902 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 if (!*args[1]) {
1907 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001911 }
1912
Willy Tarreaua534fea2008-08-03 12:19:50 +02001913 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001914 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001916 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001917 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1918
Willy Tarreau93893792009-07-23 13:19:11 +02001919 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001921 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1922 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1923 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1924 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1925 else {
1926 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 }
1930 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001931 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001932 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001933
1934 if (curproxy == &defproxy) {
1935 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_ALERT | ERR_FATAL;
1938 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001939 }
1940
1941 if (!*args[1]) {
1942 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001946 }
1947
1948 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001949 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001951 if (curproxy->uuid <= 0) {
1952 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001953 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_ALERT | ERR_FATAL;
1955 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956 }
1957
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001958 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1959 if (node) {
1960 struct proxy *target = container_of(node, struct proxy, conf.id);
1961 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1962 file, linenum, proxy_type_str(curproxy), curproxy->id,
1963 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1964 err_code |= ERR_ALERT | ERR_FATAL;
1965 goto out;
1966 }
1967 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001968 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001969 else if (!strcmp(args[0], "description")) {
1970 int i, len=0;
1971 char *d;
1972
Cyril Bonté99ed3272010-01-24 23:29:44 +01001973 if (curproxy == &defproxy) {
1974 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1975 file, linenum, args[0]);
1976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
1978 }
1979
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001980 if (!*args[1]) {
1981 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1982 file, linenum, args[0]);
1983 return -1;
1984 }
1985
1986 for(i=1; *args[i]; i++)
1987 len += strlen(args[i])+1;
1988
1989 d = (char *)calloc(1, len);
1990 curproxy->desc = d;
1991
1992 d += sprintf(d, "%s", args[1]);
1993 for(i=2; *args[i]; i++)
1994 d += sprintf(d, " %s", args[i]);
1995
1996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1998 curproxy->state = PR_STSTOPPED;
1999 }
2000 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2001 curproxy->state = PR_STNEW;
2002 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002003 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2004 int cur_arg = 1;
2005 unsigned int set = 0;
2006
2007 while (*args[cur_arg]) {
2008 int u;
2009 if (strcmp(args[cur_arg], "all") == 0) {
2010 set = 0;
2011 break;
2012 }
2013 else if (strcmp(args[cur_arg], "odd") == 0) {
2014 set |= 0x55555555;
2015 }
2016 else if (strcmp(args[cur_arg], "even") == 0) {
2017 set |= 0xAAAAAAAA;
2018 }
2019 else {
2020 u = str2uic(args[cur_arg]);
2021 if (u < 1 || u > 32) {
2022 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002026 }
2027 if (u > global.nbproc) {
2028 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002030 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002031 }
2032 set |= 1 << (u - 1);
2033 }
2034 cur_arg++;
2035 }
2036 curproxy->bind_proc = set;
2037 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002038 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002039 if (curproxy == &defproxy) {
2040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002043 }
2044
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002045 err = invalid_char(args[1]);
2046 if (err) {
2047 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2048 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002050 }
2051
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002052 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2053 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2054 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002057 }
2058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2060 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 if (*(args[1]) == 0) {
2066 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2067 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_ALERT | ERR_FATAL;
2069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002071
Willy Tarreau67402132012-05-31 20:40:20 +02002072 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002073 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002074 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002075 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 curproxy->cookie_name = strdup(args[1]);
2077 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002078
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 cur_arg = 2;
2080 while (*(args[cur_arg])) {
2081 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002082 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 }
2084 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002085 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086 }
2087 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002088 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 }
2090 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002091 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 }
2093 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002094 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002096 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002097 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002100 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002102 else if (!strcmp(args[cur_arg], "httponly")) {
2103 curproxy->ck_opts |= PR_CK_HTTPONLY;
2104 }
2105 else if (!strcmp(args[cur_arg], "secure")) {
2106 curproxy->ck_opts |= PR_CK_SECURE;
2107 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002108 else if (!strcmp(args[cur_arg], "domain")) {
2109 if (!*args[cur_arg + 1]) {
2110 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2111 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002114 }
2115
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002116 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002117 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002118 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2119 " dots nor does not start with a dot."
2120 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002121 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002122 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002123 }
2124
2125 err = invalid_domainchar(args[cur_arg + 1]);
2126 if (err) {
2127 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2128 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002131 }
2132
Willy Tarreau68a897b2009-12-03 23:28:34 +01002133 if (!curproxy->cookie_domain) {
2134 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2135 } else {
2136 /* one domain was already specified, add another one by
2137 * building the string which will be returned along with
2138 * the cookie.
2139 */
2140 char *new_ptr;
2141 int new_len = strlen(curproxy->cookie_domain) +
2142 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2143 new_ptr = malloc(new_len);
2144 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2145 free(curproxy->cookie_domain);
2146 curproxy->cookie_domain = new_ptr;
2147 }
Willy Tarreau31936852010-10-06 16:59:56 +02002148 cur_arg++;
2149 }
2150 else if (!strcmp(args[cur_arg], "maxidle")) {
2151 unsigned int maxidle;
2152 const char *res;
2153
2154 if (!*args[cur_arg + 1]) {
2155 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2156 file, linenum, args[cur_arg]);
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
2161 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2162 if (res) {
2163 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2164 file, linenum, *res, args[cur_arg]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168 curproxy->cookie_maxidle = maxidle;
2169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxlife")) {
2172 unsigned int maxlife;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <lifetime> 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], &maxlife, 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_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002190 cur_arg++;
2191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002193 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 +02002194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198 cur_arg++;
2199 }
Willy Tarreau67402132012-05-31 20:40:20 +02002200 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2202 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002203 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
2205
Willy Tarreau67402132012-05-31 20:40:20 +02002206 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2208 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002211
Willy Tarreau67402132012-05-31 20:40:20 +02002212 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002213 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2214 file, linenum);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002218 else if (!strcmp(args[0], "persist")) { /* persist */
2219 if (*(args[1]) == 0) {
2220 Alert("parsing [%s:%d] : missing persist method.\n",
2221 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002224 }
2225
2226 if (!strncmp(args[1], "rdp-cookie", 10)) {
2227 curproxy->options2 |= PR_O2_RDPC_PRST;
2228
Emeric Brunb982a3d2010-01-04 15:45:53 +01002229 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002230 const char *beg, *end;
2231
2232 beg = args[1] + 11;
2233 end = strchr(beg, ')');
2234
2235 if (!end || end == beg) {
2236 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2237 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002240 }
2241
2242 free(curproxy->rdp_cookie_name);
2243 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2244 curproxy->rdp_cookie_len = end-beg;
2245 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002246 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002247 free(curproxy->rdp_cookie_name);
2248 curproxy->rdp_cookie_name = strdup("msts");
2249 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2250 }
2251 else { /* syntax */
2252 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2253 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002256 }
2257 }
2258 else {
2259 Alert("parsing [%s:%d] : unknown persist method.\n",
2260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002263 }
2264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002266 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002278 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002284 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 curproxy->appsession_name = strdup(args[1]);
2286 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2287 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002288 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2289 if (err) {
2290 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2291 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002294 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002295 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002296
Willy Tarreau51041c72007-09-09 21:56:53 +02002297 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_ABORT;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002302
2303 cur_arg = 6;
2304 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002305 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2306 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002307 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002308 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002309 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002310 } else if (!strcmp(args[cur_arg], "prefix")) {
2311 curproxy->options2 |= PR_O2_AS_PFX;
2312 } else if (!strcmp(args[cur_arg], "mode")) {
2313 if (!*args[cur_arg + 1]) {
2314 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2315 file, linenum, args[0], args[cur_arg]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
2320 cur_arg++;
2321 if (!strcmp(args[cur_arg], "query-string")) {
2322 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2323 curproxy->options2 |= PR_O2_AS_M_QS;
2324 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2325 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2326 curproxy->options2 |= PR_O2_AS_M_PP;
2327 } else {
2328 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002333 cur_arg++;
2334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 } /* Url App Session */
2336 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002337 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002339
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002341 if (curproxy == &defproxy) {
2342 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 if (*(args[4]) == 0) {
2348 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2349 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002353 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 curproxy->capture_name = strdup(args[2]);
2355 curproxy->capture_namelen = strlen(curproxy->capture_name);
2356 curproxy->capture_len = atol(args[4]);
2357 if (curproxy->capture_len >= CAPTURE_LEN) {
2358 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2359 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 curproxy->capture_len = CAPTURE_LEN - 1;
2362 }
2363 curproxy->to_log |= LW_COOKIE;
2364 }
2365 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2366 struct cap_hdr *hdr;
2367
2368 if (curproxy == &defproxy) {
2369 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 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373
2374 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2375 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2376 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
2380
2381 hdr = calloc(sizeof(struct cap_hdr), 1);
2382 hdr->next = curproxy->req_cap;
2383 hdr->name = strdup(args[3]);
2384 hdr->namelen = strlen(args[3]);
2385 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002386 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 hdr->index = curproxy->nb_req_cap++;
2388 curproxy->req_cap = hdr;
2389 curproxy->to_log |= LW_REQHDR;
2390 }
2391 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2392 struct cap_hdr *hdr;
2393
2394 if (curproxy == &defproxy) {
2395 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 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399
2400 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2401 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2402 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 }
2406 hdr = calloc(sizeof(struct cap_hdr), 1);
2407 hdr->next = curproxy->rsp_cap;
2408 hdr->name = strdup(args[3]);
2409 hdr->namelen = strlen(args[3]);
2410 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002411 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 hdr->index = curproxy->nb_rsp_cap++;
2413 curproxy->rsp_cap = hdr;
2414 curproxy->to_log |= LW_RSPHDR;
2415 }
2416 else {
2417 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[1]) == 0) {
2428 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 curproxy->conn_retries = atol(args[1]);
2434 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002435 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002436 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002437
2438 if (curproxy == &defproxy) {
2439 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
Willy Tarreauff011f22011-01-06 17:51:27 +01002444 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 +01002445 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_WARN;
2448 }
2449
Willy Tarreauff011f22011-01-06 17:51:27 +01002450 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002451
Willy Tarreauff011f22011-01-06 17:51:27 +01002452 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002453 err_code |= ERR_ALERT | ERR_ABORT;
2454 goto out;
2455 }
2456
Willy Tarreauff011f22011-01-06 17:51:27 +01002457 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2458 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002459 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002460 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2461 /* set the header name and length into the proxy structure */
2462 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2463 err_code |= ERR_WARN;
2464
2465 if (!*args[1]) {
2466 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2467 file, linenum, args[0]);
2468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
2470 }
2471
2472 /* set the desired header name */
2473 free(curproxy->server_id_hdr_name);
2474 curproxy->server_id_hdr_name = strdup(args[1]);
2475 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2476 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002477 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002478 if (curproxy == &defproxy) {
2479 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002482 }
2483
Willy Tarreauef6494c2010-01-28 17:12:36 +01002484 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002485 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2486 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002489 }
2490
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002491 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2492 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2493 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002496 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002497
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002498 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002499 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002500 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002501 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002502 struct redirect_rule *rule;
2503 int cur_arg;
2504 int type = REDIRECT_TYPE_NONE;
2505 int code = 302;
2506 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002507 char *cookie = NULL;
2508 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002509 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002510
Cyril Bonté99ed3272010-01-24 23:29:44 +01002511 if (curproxy == &defproxy) {
2512 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
2515 }
2516
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002517 cur_arg = 1;
2518 while (*(args[cur_arg])) {
2519 if (!strcmp(args[cur_arg], "location")) {
2520 if (!*args[cur_arg + 1]) {
2521 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2522 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002525 }
2526
2527 type = REDIRECT_TYPE_LOCATION;
2528 cur_arg++;
2529 destination = args[cur_arg];
2530 }
2531 else if (!strcmp(args[cur_arg], "prefix")) {
2532 if (!*args[cur_arg + 1]) {
2533 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2534 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002537 }
2538
2539 type = REDIRECT_TYPE_PREFIX;
2540 cur_arg++;
2541 destination = args[cur_arg];
2542 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002543 else if (!strcmp(args[cur_arg], "scheme")) {
2544 if (!*args[cur_arg + 1]) {
2545 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2546 file, linenum, args[0], args[cur_arg]);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
2549 }
2550
2551 type = REDIRECT_TYPE_SCHEME;
2552 cur_arg++;
2553 destination = args[cur_arg];
2554 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002555 else if (!strcmp(args[cur_arg], "set-cookie")) {
2556 if (!*args[cur_arg + 1]) {
2557 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2558 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002561 }
2562
2563 cur_arg++;
2564 cookie = args[cur_arg];
2565 cookie_set = 1;
2566 }
2567 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2568 if (!*args[cur_arg + 1]) {
2569 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2570 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002573 }
2574
2575 cur_arg++;
2576 cookie = args[cur_arg];
2577 cookie_set = 0;
2578 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 else if (!strcmp(args[cur_arg],"code")) {
2580 if (!*args[cur_arg + 1]) {
2581 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002585 }
2586 cur_arg++;
2587 code = atol(args[cur_arg]);
2588 if (code < 301 || code > 303) {
2589 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2590 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 }
2594 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002595 else if (!strcmp(args[cur_arg],"drop-query")) {
2596 flags |= REDIRECT_FLAG_DROP_QS;
2597 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002598 else if (!strcmp(args[cur_arg],"append-slash")) {
2599 flags |= REDIRECT_FLAG_APPEND_SLASH;
2600 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002601 else if (strcmp(args[cur_arg], "if") == 0 ||
2602 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002603 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002604 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002605 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2606 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
2609 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002610 break;
2611 }
2612 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002613 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 +02002614 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 }
2618 cur_arg++;
2619 }
2620
2621 if (type == REDIRECT_TYPE_NONE) {
2622 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
2627
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2629 rule->cond = cond;
2630 rule->rdr_str = strdup(destination);
2631 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002632 if (cookie) {
2633 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002634 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002635 */
2636 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002637 if (cookie_set) {
2638 rule->cookie_str = malloc(rule->cookie_len + 10);
2639 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2640 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2641 rule->cookie_len += 9;
2642 } else {
2643 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002644 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002645 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2646 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002647 }
2648 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002649 rule->type = type;
2650 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002651 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002652 LIST_INIT(&rule->list);
2653 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002654 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2655 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002656 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002657 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 struct switching_rule *rule;
2659
Willy Tarreaub099aca2008-10-12 17:26:37 +02002660 if (curproxy == &defproxy) {
2661 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002664 }
2665
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002668
2669 if (*(args[1]) == 0) {
2670 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 }
2674
Willy Tarreauef6494c2010-01-28 17:12:36 +01002675 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 }
2681
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002682 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2683 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2684 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 }
2688
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002689 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002690
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2692 rule->cond = cond;
2693 rule->be.name = strdup(args[1]);
2694 LIST_INIT(&rule->list);
2695 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2696 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002697 else if (strcmp(args[0], "use-server") == 0) {
2698 struct server_rule *rule;
2699
2700 if (curproxy == &defproxy) {
2701 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
2704 }
2705
2706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2707 err_code |= ERR_WARN;
2708
2709 if (*(args[1]) == 0) {
2710 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
2715 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2716 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2717 file, linenum, args[0]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002722 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2723 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2724 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
2729 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2730
2731 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2732 rule->cond = cond;
2733 rule->srv.name = strdup(args[1]);
2734 LIST_INIT(&rule->list);
2735 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2736 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2737 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002738 else if ((!strcmp(args[0], "force-persist")) ||
2739 (!strcmp(args[0], "ignore-persist"))) {
2740 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002741
2742 if (curproxy == &defproxy) {
2743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
2747
2748 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2749 err_code |= ERR_WARN;
2750
Willy Tarreauef6494c2010-01-28 17:12:36 +01002751 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002752 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2753 file, linenum, args[0]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002758 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2759 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2760 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002761 err_code |= ERR_ALERT | ERR_FATAL;
2762 goto out;
2763 }
2764
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002765 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002766
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002767 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002768 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002769 if (!strcmp(args[0], "force-persist")) {
2770 rule->type = PERSIST_TYPE_FORCE;
2771 } else {
2772 rule->type = PERSIST_TYPE_IGNORE;
2773 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002774 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002775 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002776 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002777 else if (!strcmp(args[0], "stick-table")) {
2778 int myidx = 1;
2779
Emeric Brun32da3c42010-09-23 18:39:19 +02002780 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002781 curproxy->table.type = (unsigned int)-1;
2782 while (*args[myidx]) {
2783 const char *err;
2784
2785 if (strcmp(args[myidx], "size") == 0) {
2786 myidx++;
2787 if (!*(args[myidx])) {
2788 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2789 file, linenum, args[myidx-1]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2794 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2795 file, linenum, *err, args[myidx-1]);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002799 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002800 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002801 else if (strcmp(args[myidx], "peers") == 0) {
2802 myidx++;
2803 if (!*(args[myidx])) {
2804 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2805 file, linenum, args[myidx-1]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
2809 curproxy->table.peers.name = strdup(args[myidx++]);
2810 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002811 else if (strcmp(args[myidx], "expire") == 0) {
2812 myidx++;
2813 if (!*(args[myidx])) {
2814 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2815 file, linenum, args[myidx-1]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2820 if (err) {
2821 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2822 file, linenum, *err, args[myidx-1]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825 }
2826 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002827 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002828 }
2829 else if (strcmp(args[myidx], "nopurge") == 0) {
2830 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002831 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 }
2833 else if (strcmp(args[myidx], "type") == 0) {
2834 myidx++;
2835 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2836 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2837 file, linenum, args[myidx]);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002841 /* myidx already points to next arg */
2842 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002843 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002844 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002845 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002846
2847 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002848 nw = args[myidx];
2849 while (*nw) {
2850 /* the "store" keyword supports a comma-separated list */
2851 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002852 sa = NULL; /* store arg */
2853 while (*nw && *nw != ',') {
2854 if (*nw == '(') {
2855 *nw = 0;
2856 sa = ++nw;
2857 while (*nw != ')') {
2858 if (!*nw) {
2859 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2860 file, linenum, args[0], cw);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864 nw++;
2865 }
2866 *nw = '\0';
2867 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002868 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002869 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002870 if (*nw)
2871 *nw++ = '\0';
2872 type = stktable_get_data_type(cw);
2873 if (type < 0) {
2874 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2875 file, linenum, args[0], cw);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
Willy Tarreauac782882010-06-20 10:41:54 +02002879
2880 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2881 switch (err) {
2882 case PE_NONE: break;
2883 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002884 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2885 file, linenum, args[0], cw);
2886 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002887 break;
2888
2889 case PE_ARG_MISSING:
2890 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2891 file, linenum, args[0], cw);
2892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894
2895 case PE_ARG_NOT_USED:
2896 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2897 file, linenum, args[0], cw);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900
2901 default:
2902 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2903 file, linenum, args[0], cw);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002906 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002907 }
2908 myidx++;
2909 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002910 else {
2911 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2912 file, linenum, args[myidx]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002915 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002916 }
2917
2918 if (!curproxy->table.size) {
2919 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2920 file, linenum);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
2923 }
2924
2925 if (curproxy->table.type == (unsigned int)-1) {
2926 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2927 file, linenum);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
2931 }
2932 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002933 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002934 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 int myidx = 0;
2936 const char *name = NULL;
2937 int flags;
2938
2939 if (curproxy == &defproxy) {
2940 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944
2945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2946 err_code |= ERR_WARN;
2947 goto out;
2948 }
2949
2950 myidx++;
2951 if ((strcmp(args[myidx], "store") == 0) ||
2952 (strcmp(args[myidx], "store-request") == 0)) {
2953 myidx++;
2954 flags = STK_IS_STORE;
2955 }
2956 else if (strcmp(args[myidx], "store-response") == 0) {
2957 myidx++;
2958 flags = STK_IS_STORE | STK_ON_RSP;
2959 }
2960 else if (strcmp(args[myidx], "match") == 0) {
2961 myidx++;
2962 flags = STK_IS_MATCH;
2963 }
2964 else if (strcmp(args[myidx], "on") == 0) {
2965 myidx++;
2966 flags = STK_IS_MATCH | STK_IS_STORE;
2967 }
2968 else {
2969 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
2972 }
2973
2974 if (*(args[myidx]) == 0) {
2975 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002980 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002981 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002982 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986
2987 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002988 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002989 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2990 file, linenum, args[0], expr->fetch->kw);
2991 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002992 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002993 goto out;
2994 }
2995 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002996 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002997 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2998 file, linenum, args[0], expr->fetch->kw);
2999 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003000 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 goto out;
3002 }
3003 }
3004
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003005 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3006 if (expr->fetch->cap & SMP_CAP_L7)
3007 curproxy->acl_requires |= ACL_USE_L7_ANY;
3008
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 if (strcmp(args[myidx], "table") == 0) {
3010 myidx++;
3011 name = args[myidx++];
3012 }
3013
Willy Tarreauef6494c2010-01-28 17:12:36 +01003014 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003015 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3016 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3017 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003018 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003019 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 goto out;
3021 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003022 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003023 else if (*(args[myidx])) {
3024 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3025 file, linenum, args[0], args[myidx]);
3026 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003027 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003028 goto out;
3029 }
Emeric Brun97679e72010-09-23 17:56:44 +02003030 if (flags & STK_ON_RSP)
3031 err_code |= warnif_cond_requires_req(cond, file, linenum);
3032 else
3033 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003034
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3036 rule->cond = cond;
3037 rule->expr = expr;
3038 rule->flags = flags;
3039 rule->table.name = name ? strdup(name) : NULL;
3040 LIST_INIT(&rule->list);
3041 if (flags & STK_ON_RSP)
3042 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3043 else
3044 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3051 curproxy->uri_auth = NULL; /* we must detach from the default config */
3052
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003053 if (!*args[1]) {
3054 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003055 } else if (!strcmp(args[1], "admin")) {
3056 struct stats_admin_rule *rule;
3057
3058 if (curproxy == &defproxy) {
3059 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
3062 }
3063
3064 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3065 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3066 err_code |= ERR_ALERT | ERR_ABORT;
3067 goto out;
3068 }
3069
3070 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3071 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3072 file, linenum, args[0], args[1]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
3075 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003076 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3077 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3078 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
3081 }
3082
3083 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3084
3085 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3086 rule->cond = cond;
3087 LIST_INIT(&rule->list);
3088 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 } else if (!strcmp(args[1], "uri")) {
3090 if (*(args[2]) == 0) {
3091 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3095 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 }
3099 } else if (!strcmp(args[1], "realm")) {
3100 if (*(args[2]) == 0) {
3101 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3105 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_ABORT;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003109 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003110 unsigned interval;
3111
3112 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3113 if (err) {
3114 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3115 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003118 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3119 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_ABORT;
3121 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003122 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003123 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003124 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003125
3126 if (curproxy == &defproxy) {
3127 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131
3132 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3133 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3134 err_code |= ERR_ALERT | ERR_ABORT;
3135 goto out;
3136 }
3137
Willy Tarreauff011f22011-01-06 17:51:27 +01003138 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3139 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003140 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3141 file, linenum, args[0]);
3142 err_code |= ERR_WARN;
3143 }
3144
Willy Tarreauff011f22011-01-06 17:51:27 +01003145 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003146
Willy Tarreauff011f22011-01-06 17:51:27 +01003147 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003148 err_code |= ERR_ALERT | ERR_ABORT;
3149 goto out;
3150 }
3151
Willy Tarreauff011f22011-01-06 17:51:27 +01003152 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3153 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003154
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 } else if (!strcmp(args[1], "auth")) {
3156 if (*(args[2]) == 0) {
3157 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3161 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_ABORT;
3163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 }
3165 } else if (!strcmp(args[1], "scope")) {
3166 if (*(args[2]) == 0) {
3167 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3171 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_ABORT;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 }
3175 } else if (!strcmp(args[1], "enable")) {
3176 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3177 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_ABORT;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003181 } else if (!strcmp(args[1], "hide-version")) {
3182 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3183 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_ABORT;
3185 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003186 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003187 } else if (!strcmp(args[1], "show-legends")) {
3188 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3189 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3190 err_code |= ERR_ALERT | ERR_ABORT;
3191 goto out;
3192 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003193 } else if (!strcmp(args[1], "show-node")) {
3194
3195 if (*args[2]) {
3196 int i;
3197 char c;
3198
3199 for (i=0; args[2][i]; i++) {
3200 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003201 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3202 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003203 break;
3204 }
3205
3206 if (!i || args[2][i]) {
3207 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3208 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3209 file, linenum, args[0], args[1]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213 }
3214
3215 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3216 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3217 err_code |= ERR_ALERT | ERR_ABORT;
3218 goto out;
3219 }
3220 } else if (!strcmp(args[1], "show-desc")) {
3221 char *desc = NULL;
3222
3223 if (*args[2]) {
3224 int i, len=0;
3225 char *d;
3226
3227 for(i=2; *args[i]; i++)
3228 len += strlen(args[i])+1;
3229
3230 desc = d = (char *)calloc(1, len);
3231
3232 d += sprintf(d, "%s", args[2]);
3233 for(i=3; *args[i]; i++)
3234 d += sprintf(d, " %s", args[i]);
3235 }
3236
3237 if (!*args[2] && !global.desc)
3238 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3239 file, linenum, args[1]);
3240 else {
3241 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3242 free(desc);
3243 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3244 err_code |= ERR_ALERT | ERR_ABORT;
3245 goto out;
3246 }
3247 free(desc);
3248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003250stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003251 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 +01003252 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
3256 }
3257 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003258 int optnum;
3259
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003260 if (*(args[1]) == '\0') {
3261 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3262 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003266
3267 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3268 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003269 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3270 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3271 file, linenum, cfg_opts[optnum].name);
3272 err_code |= ERR_ALERT | ERR_FATAL;
3273 goto out;
3274 }
Willy Tarreau93893792009-07-23 13:19:11 +02003275 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3276 err_code |= ERR_WARN;
3277 goto out;
3278 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003279
Willy Tarreau3842f002009-06-14 11:39:52 +02003280 curproxy->no_options &= ~cfg_opts[optnum].val;
3281 curproxy->options &= ~cfg_opts[optnum].val;
3282
3283 switch (kwm) {
3284 case KWM_STD:
3285 curproxy->options |= cfg_opts[optnum].val;
3286 break;
3287 case KWM_NO:
3288 curproxy->no_options |= cfg_opts[optnum].val;
3289 break;
3290 case KWM_DEF: /* already cleared */
3291 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003292 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003293
Willy Tarreau93893792009-07-23 13:19:11 +02003294 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295 }
3296 }
3297
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003298 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3299 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003300 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3301 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3302 file, linenum, cfg_opts2[optnum].name);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305 }
Willy Tarreau93893792009-07-23 13:19:11 +02003306 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3307 err_code |= ERR_WARN;
3308 goto out;
3309 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003310
Willy Tarreau3842f002009-06-14 11:39:52 +02003311 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3312 curproxy->options2 &= ~cfg_opts2[optnum].val;
3313
3314 switch (kwm) {
3315 case KWM_STD:
3316 curproxy->options2 |= cfg_opts2[optnum].val;
3317 break;
3318 case KWM_NO:
3319 curproxy->no_options2 |= cfg_opts2[optnum].val;
3320 break;
3321 case KWM_DEF: /* already cleared */
3322 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003323 }
Willy Tarreau93893792009-07-23 13:19:11 +02003324 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003325 }
3326 }
3327
Willy Tarreau3842f002009-06-14 11:39:52 +02003328 if (kwm != KWM_STD) {
3329 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003330 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003333 }
3334
Emeric Brun3a058f32009-06-30 18:26:00 +02003335 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003336 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003338 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003339 if (*(args[2]) != '\0') {
3340 if (!strcmp(args[2], "clf")) {
3341 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003342 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003343 } else {
3344 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003347 }
3348 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003349 if (curproxy->logformat_string != default_http_log_format &&
3350 curproxy->logformat_string != default_tcp_log_format &&
3351 curproxy->logformat_string != clf_http_log_format)
3352 free(curproxy->logformat_string);
3353 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003354 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003355 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003357 if (curproxy->logformat_string != default_http_log_format &&
3358 curproxy->logformat_string != default_tcp_log_format &&
3359 curproxy->logformat_string != clf_http_log_format)
3360 free(curproxy->logformat_string);
3361 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003362 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 else if (!strcmp(args[1], "tcpka")) {
3364 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003365 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003366 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003367
3368 if (curproxy->cap & PR_CAP_FE)
3369 curproxy->options |= PR_O_TCP_CLI_KA;
3370 if (curproxy->cap & PR_CAP_BE)
3371 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003374 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003375 err_code |= ERR_WARN;
3376
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003378 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003379 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003380 curproxy->options2 &= ~PR_O2_CHK_ANY;
3381 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 if (!*args[2]) { /* no argument */
3383 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3384 curproxy->check_len = strlen(DEF_CHECK_REQ);
3385 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003386 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 curproxy->check_req = (char *)malloc(reqlen);
3388 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003389 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003391 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 if (*args[4])
3393 reqlen += strlen(args[4]);
3394 else
3395 reqlen += strlen("HTTP/1.0");
3396
3397 curproxy->check_req = (char *)malloc(reqlen);
3398 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003399 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003401 }
3402 else if (!strcmp(args[1], "ssl-hello-chk")) {
3403 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003404 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003406
Willy Tarreaua534fea2008-08-03 12:19:50 +02003407 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003408 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003409 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003410 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Willy Tarreau23677902007-05-08 23:50:35 +02003412 else if (!strcmp(args[1], "smtpchk")) {
3413 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003414 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003415 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003416 curproxy->options2 &= ~PR_O2_CHK_ANY;
3417 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003418
3419 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3420 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3421 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3422 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3423 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3424 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3425 curproxy->check_req = (char *)malloc(reqlen);
3426 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3427 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3428 } else {
3429 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3430 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3431 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3432 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3433 }
3434 }
3435 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003436 else if (!strcmp(args[1], "pgsql-check")) {
3437 /* use PostgreSQL request to check servers' health */
3438 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3439 err_code |= ERR_WARN;
3440
3441 free(curproxy->check_req);
3442 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003443 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003444 curproxy->options2 |= PR_O2_PGSQL_CHK;
3445
3446 if (*(args[2])) {
3447 int cur_arg = 2;
3448
3449 while (*(args[cur_arg])) {
3450 if (strcmp(args[cur_arg], "user") == 0) {
3451 char * packet;
3452 uint32_t packet_len;
3453 uint32_t pv;
3454
3455 /* suboption header - needs additional argument for it */
3456 if (*(args[cur_arg+1]) == 0) {
3457 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3458 file, linenum, args[0], args[1], args[cur_arg]);
3459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
3461 }
3462
3463 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3464 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3465 pv = htonl(0x30000); /* protocol version 3.0 */
3466
3467 packet = (char*) calloc(1, packet_len);
3468
3469 memcpy(packet + 4, &pv, 4);
3470
3471 /* copy "user" */
3472 memcpy(packet + 8, "user", 4);
3473
3474 /* copy username */
3475 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3476
3477 free(curproxy->check_req);
3478 curproxy->check_req = packet;
3479 curproxy->check_len = packet_len;
3480
3481 packet_len = htonl(packet_len);
3482 memcpy(packet, &packet_len, 4);
3483 cur_arg += 2;
3484 } else {
3485 /* unknown suboption - catchall */
3486 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3487 file, linenum, args[0], args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 } /* end while loop */
3492 }
3493 }
3494
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003495 else if (!strcmp(args[1], "redis-check")) {
3496 /* use REDIS PING request to check servers' health */
3497 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3498 err_code |= ERR_WARN;
3499
3500 free(curproxy->check_req);
3501 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003502 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003503 curproxy->options2 |= PR_O2_REDIS_CHK;
3504
3505 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3506 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3507 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3508 }
3509
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003510 else if (!strcmp(args[1], "mysql-check")) {
3511 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3513 err_code |= ERR_WARN;
3514
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003515 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003516 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003517 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003518 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003519
3520 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3521 * const char mysql40_client_auth_pkt[] = {
3522 * "\x0e\x00\x00" // packet length
3523 * "\x01" // packet number
3524 * "\x00\x00" // client capabilities
3525 * "\x00\x00\x01" // max packet
3526 * "haproxy\x00" // username (null terminated string)
3527 * "\x00" // filler (always 0x00)
3528 * "\x01\x00\x00" // packet length
3529 * "\x00" // packet number
3530 * "\x01" // COM_QUIT command
3531 * };
3532 */
3533
3534 if (*(args[2])) {
3535 int cur_arg = 2;
3536
3537 while (*(args[cur_arg])) {
3538 if (strcmp(args[cur_arg], "user") == 0) {
3539 char *mysqluser;
3540 int packetlen, reqlen, userlen;
3541
3542 /* suboption header - needs additional argument for it */
3543 if (*(args[cur_arg+1]) == 0) {
3544 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3545 file, linenum, args[0], args[1], args[cur_arg]);
3546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
3548 }
3549 mysqluser = args[cur_arg + 1];
3550 userlen = strlen(mysqluser);
3551 packetlen = userlen + 7;
3552 reqlen = packetlen + 9;
3553
3554 free(curproxy->check_req);
3555 curproxy->check_req = (char *)calloc(1, reqlen);
3556 curproxy->check_len = reqlen;
3557
3558 snprintf(curproxy->check_req, 4, "%c%c%c",
3559 ((unsigned char) packetlen & 0xff),
3560 ((unsigned char) (packetlen >> 8) & 0xff),
3561 ((unsigned char) (packetlen >> 16) & 0xff));
3562
3563 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003564 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003565 curproxy->check_req[8] = 1;
3566 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3567 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3568 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3569 cur_arg += 2;
3570 } else {
3571 /* unknown suboption - catchall */
3572 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3573 file, linenum, args[0], args[1]);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576 }
3577 } /* end while loop */
3578 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003579 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003580 else if (!strcmp(args[1], "ldap-check")) {
3581 /* use LDAP request to check servers' health */
3582 free(curproxy->check_req);
3583 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003584 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003585 curproxy->options2 |= PR_O2_LDAP_CHK;
3586
3587 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3588 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3589 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3590 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003591 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003592 int cur_arg;
3593
3594 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3595 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003596 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003597
Willy Tarreau87cf5142011-08-19 22:57:24 +02003598 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003599
3600 free(curproxy->fwdfor_hdr_name);
3601 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3602 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3603
3604 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3605 cur_arg = 2;
3606 while (*(args[cur_arg])) {
3607 if (!strcmp(args[cur_arg], "except")) {
3608 /* suboption except - needs additional argument for it */
3609 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3610 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3611 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003614 }
3615 /* flush useless bits */
3616 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003617 cur_arg += 2;
3618 } else if (!strcmp(args[cur_arg], "header")) {
3619 /* suboption header - needs additional argument for it */
3620 if (*(args[cur_arg+1]) == 0) {
3621 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3622 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003625 }
3626 free(curproxy->fwdfor_hdr_name);
3627 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3628 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3629 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003630 } else if (!strcmp(args[cur_arg], "if-none")) {
3631 curproxy->options &= ~PR_O_FF_ALWAYS;
3632 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003633 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003634 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003635 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003636 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_FATAL;
3638 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003639 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003640 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003641 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003642 else if (!strcmp(args[1], "originalto")) {
3643 int cur_arg;
3644
3645 /* insert x-original-to field, but not for the IP address listed as an except.
3646 * set default options (ie: bitfield, header name, etc)
3647 */
3648
3649 curproxy->options |= PR_O_ORGTO;
3650
3651 free(curproxy->orgto_hdr_name);
3652 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3653 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3654
Willy Tarreau87cf5142011-08-19 22:57:24 +02003655 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003656 cur_arg = 2;
3657 while (*(args[cur_arg])) {
3658 if (!strcmp(args[cur_arg], "except")) {
3659 /* suboption except - needs additional argument for it */
3660 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3662 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003665 }
3666 /* flush useless bits */
3667 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3668 cur_arg += 2;
3669 } else if (!strcmp(args[cur_arg], "header")) {
3670 /* suboption header - needs additional argument for it */
3671 if (*(args[cur_arg+1]) == 0) {
3672 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3673 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003676 }
3677 free(curproxy->orgto_hdr_name);
3678 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3679 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3680 cur_arg += 2;
3681 } else {
3682 /* unknown suboption - catchall */
3683 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3684 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003687 }
3688 } /* end while loop */
3689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003690 else {
3691 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 }
Willy Tarreau93893792009-07-23 13:19:11 +02003695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003697 else if (!strcmp(args[0], "default_backend")) {
3698 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003699 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003700
3701 if (*(args[1]) == 0) {
3702 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003705 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003706 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003707 curproxy->defbe.name = strdup(args[1]);
3708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003712
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003713 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003715 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 /* enable reconnections to dispatch */
3717 curproxy->options |= PR_O_REDISP;
3718 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003719 else if (!strcmp(args[0], "http-check")) {
3720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003722
3723 if (strcmp(args[1], "disable-on-404") == 0) {
3724 /* enable a graceful server shutdown on an HTTP 404 response */
3725 curproxy->options |= PR_O_DISABLE404;
3726 }
Willy Tarreauef781042010-01-27 11:53:01 +01003727 else if (strcmp(args[1], "send-state") == 0) {
3728 /* enable emission of the apparent state of a server in HTTP checks */
3729 curproxy->options2 |= PR_O2_CHK_SNDST;
3730 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003731 else if (strcmp(args[1], "expect") == 0) {
3732 const char *ptr_arg;
3733 int cur_arg;
3734
3735 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3736 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
3739 }
3740
3741 cur_arg = 2;
3742 /* consider exclamation marks, sole or at the beginning of a word */
3743 while (*(ptr_arg = args[cur_arg])) {
3744 while (*ptr_arg == '!') {
3745 curproxy->options2 ^= PR_O2_EXP_INV;
3746 ptr_arg++;
3747 }
3748 if (*ptr_arg)
3749 break;
3750 cur_arg++;
3751 }
3752 /* now ptr_arg points to the beginning of a word past any possible
3753 * exclamation mark, and cur_arg is the argument which holds this word.
3754 */
3755 if (strcmp(ptr_arg, "status") == 0) {
3756 if (!*(args[cur_arg + 1])) {
3757 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3758 file, linenum, args[0], args[1], ptr_arg);
3759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003763 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003764 curproxy->expect_str = strdup(args[cur_arg + 1]);
3765 }
3766 else if (strcmp(ptr_arg, "string") == 0) {
3767 if (!*(args[cur_arg + 1])) {
3768 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3769 file, linenum, args[0], args[1], ptr_arg);
3770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
3772 }
3773 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003774 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003775 curproxy->expect_str = strdup(args[cur_arg + 1]);
3776 }
3777 else if (strcmp(ptr_arg, "rstatus") == 0) {
3778 if (!*(args[cur_arg + 1])) {
3779 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3780 file, linenum, args[0], args[1], ptr_arg);
3781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
3783 }
3784 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003785 free(curproxy->expect_str);
3786 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3787 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003788 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3789 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3790 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3791 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
3794 }
3795 }
3796 else if (strcmp(ptr_arg, "rstring") == 0) {
3797 if (!*(args[cur_arg + 1])) {
3798 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3799 file, linenum, args[0], args[1], ptr_arg);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003804 free(curproxy->expect_str);
3805 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3806 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003807 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3808 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3809 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3810 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
3813 }
3814 }
3815 else {
3816 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3817 file, linenum, args[0], args[1], ptr_arg);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
3821 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003822 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003823 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 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003826 }
3827 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003828 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003833 }
3834
Willy Tarreaub80c2302007-11-30 20:51:32 +01003835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003837
3838 if (strcmp(args[1], "fail") == 0) {
3839 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003840 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003841 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3842 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003843 err_code |= ERR_ALERT | ERR_FATAL;
3844 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003845 }
3846
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003847 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3848 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3849 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003852 }
3853 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3854 }
3855 else {
3856 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003859 }
3860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861#ifdef TPROXY
3862 else if (!strcmp(args[0], "transparent")) {
3863 /* enable transparent proxy connections */
3864 curproxy->options |= PR_O_TRANSP;
3865 }
3866#endif
3867 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003868 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003870
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 if (*(args[1]) == 0) {
3872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_ALERT | ERR_FATAL;
3874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003875 }
3876 curproxy->maxconn = atol(args[1]);
3877 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003878 else if (!strcmp(args[0], "backlog")) { /* backlog */
3879 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003880 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003881
3882 if (*(args[1]) == 0) {
3883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003886 }
3887 curproxy->backlog = atol(args[1]);
3888 }
Willy Tarreau86034312006-12-29 00:10:33 +01003889 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003890 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003892
Willy Tarreau86034312006-12-29 00:10:33 +01003893 if (*(args[1]) == 0) {
3894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003897 }
3898 curproxy->fullconn = atol(args[1]);
3899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3901 if (*(args[1]) == 0) {
3902 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003905 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003906 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3907 if (err) {
3908 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3909 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003912 }
3913 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 }
3915 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003916 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 if (curproxy == &defproxy) {
3918 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003922 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003924
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 if (strchr(args[1], ':') == NULL) {
3926 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003930 sk = str2sa(args[1]);
3931 if (!sk) {
3932 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3933 err_code |= ERR_ALERT | ERR_FATAL;
3934 goto out;
3935 }
3936 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003937 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
3939 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003940 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003942
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003943 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3944 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003949 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3951 err_code |= ERR_WARN;
3952
3953 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3954 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3955 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3956 }
3957 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3958 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3959 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3960 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003961 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3962 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3963 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3964 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003965 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003966 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
3970 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003973 char *rport, *raddr;
3974 short realport = 0;
3975 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003977 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003982 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003983 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984
3985 if (!*args[2]) {
3986 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3987 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003991
3992 err = invalid_char(args[1]);
3993 if (err) {
3994 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3995 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003998 }
3999
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004000 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004001 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004002
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004003 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4004 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4005 err_code |= ERR_ALERT | ERR_ABORT;
4006 goto out;
4007 }
4008
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004009 /* the servers are linked backwards first */
4010 newsrv->next = curproxy->srv;
4011 curproxy->srv = newsrv;
4012 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004013 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004014 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004015
Simon Hormanaf514952011-06-21 14:34:57 +09004016 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 LIST_INIT(&newsrv->pendconns);
4018 do_check = 0;
4019 newsrv->state = SRV_RUNNING; /* early server setup */
4020 newsrv->last_change = now.tv_sec;
4021 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004023 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004024 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 * - IP: => port=+0, relative
4026 * - IP:N => port=N, absolute
4027 * - IP:+N => port=+N, relative
4028 * - IP:-N => port=-N, relative
4029 */
4030 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004031 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004032 if (rport) {
4033 *rport++ = 0;
4034 realport = atol(rport);
4035 if (!isdigit((unsigned char)*rport))
4036 newsrv->state |= SRV_MAPPORTS;
4037 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004039
Willy Tarreaufab5a432011-03-04 15:31:53 +01004040 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004042 if (!sk) {
4043 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004048 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4049 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004050
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004051 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004052 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4053 file, linenum, newsrv->addr.ss_family, args[2]);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004057 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004058
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004059 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004060 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004061 newsrv->inter = curproxy->defsrv.inter;
4062 newsrv->fastinter = curproxy->defsrv.fastinter;
4063 newsrv->downinter = curproxy->defsrv.downinter;
4064 newsrv->rise = curproxy->defsrv.rise;
4065 newsrv->fall = curproxy->defsrv.fall;
4066 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4067 newsrv->minconn = curproxy->defsrv.minconn;
4068 newsrv->maxconn = curproxy->defsrv.maxconn;
4069 newsrv->slowstart = curproxy->defsrv.slowstart;
4070 newsrv->onerror = curproxy->defsrv.onerror;
4071 newsrv->consecutive_errors_limit
4072 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004073#ifdef OPENSSL
4074 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4075#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004076 newsrv->uweight = newsrv->iweight
4077 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004081 cur_arg = 3;
4082 } else {
4083 newsrv = &curproxy->defsrv;
4084 cur_arg = 1;
4085 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004086
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004088 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004089 newsrv->cookie = strdup(args[cur_arg + 1]);
4090 newsrv->cklen = strlen(args[cur_arg + 1]);
4091 cur_arg += 2;
4092 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004093 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004094 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4095 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4096 cur_arg += 2;
4097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004098 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004099 if (!*args[cur_arg + 1]) {
4100 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4101 file, linenum, args[cur_arg]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
4105
Willy Tarreaubaaee002006-06-26 02:48:02 +02004106 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004107 if (newsrv->rise <= 0) {
4108 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4109 file, linenum, args[cur_arg]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
4113
Willy Tarreau96839092010-03-29 10:02:24 +02004114 if (newsrv->health)
4115 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004116 cur_arg += 2;
4117 }
4118 else if (!strcmp(args[cur_arg], "fall")) {
4119 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004120
4121 if (!*args[cur_arg + 1]) {
4122 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4123 file, linenum, args[cur_arg]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127
4128 if (newsrv->fall <= 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 Tarreaubaaee002006-06-26 02:48:02 +02004135 cur_arg += 2;
4136 }
4137 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004138 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4139 if (err) {
4140 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4141 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004144 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004145 if (val <= 0) {
4146 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4147 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004150 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004151 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 cur_arg += 2;
4153 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004154 else if (!strcmp(args[cur_arg], "fastinter")) {
4155 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4156 if (err) {
4157 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4158 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004161 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004162 if (val <= 0) {
4163 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4164 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004167 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004168 newsrv->fastinter = val;
4169 cur_arg += 2;
4170 }
4171 else if (!strcmp(args[cur_arg], "downinter")) {
4172 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4173 if (err) {
4174 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4175 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004178 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004179 if (val <= 0) {
4180 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4181 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004185 newsrv->downinter = val;
4186 cur_arg += 2;
4187 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004188 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004189 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004190 if (!sk) {
4191 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004195 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004196 cur_arg += 2;
4197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004199 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 cur_arg += 2;
4201 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 newsrv->state |= SRV_BACKUP;
4204 cur_arg ++;
4205 }
Simon Hormanfa461682011-06-25 09:39:49 +09004206 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4207 newsrv->state |= SRV_NON_STICK;
4208 cur_arg ++;
4209 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4211 newsrv->state |= SRV_SEND_PROXY;
4212 cur_arg ++;
4213 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004214 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4215 newsrv->check.send_proxy = 1;
4216 cur_arg ++;
4217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 else if (!strcmp(args[cur_arg], "weight")) {
4219 int w;
4220 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004221 if (w < 0 || w > 256) {
4222 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004227 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 cur_arg += 2;
4229 }
4230 else if (!strcmp(args[cur_arg], "minconn")) {
4231 newsrv->minconn = atol(args[cur_arg + 1]);
4232 cur_arg += 2;
4233 }
4234 else if (!strcmp(args[cur_arg], "maxconn")) {
4235 newsrv->maxconn = atol(args[cur_arg + 1]);
4236 cur_arg += 2;
4237 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004238 else if (!strcmp(args[cur_arg], "maxqueue")) {
4239 newsrv->maxqueue = atol(args[cur_arg + 1]);
4240 cur_arg += 2;
4241 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004242 else if (!strcmp(args[cur_arg], "slowstart")) {
4243 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004244 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004245 if (err) {
4246 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4247 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004250 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004251 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004252 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4253 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004256 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004257 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004258 cur_arg += 2;
4259 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004260 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004261
4262 if (!*args[cur_arg + 1]) {
4263 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4264 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004267 }
4268
4269 newsrv->trackit = strdup(args[cur_arg + 1]);
4270
4271 cur_arg += 2;
4272 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004273 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 global.maxsock++;
4275 do_check = 1;
4276 cur_arg += 1;
4277 }
Willy Tarreau96839092010-03-29 10:02:24 +02004278 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4279 newsrv->state |= SRV_MAINTAIN;
4280 newsrv->state &= ~SRV_RUNNING;
4281 newsrv->health = 0;
4282 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004283 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004284 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004285 if (!strcmp(args[cur_arg + 1], "none"))
4286 newsrv->observe = HANA_OBS_NONE;
4287 else if (!strcmp(args[cur_arg + 1], "layer4"))
4288 newsrv->observe = HANA_OBS_LAYER4;
4289 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4290 if (curproxy->mode != PR_MODE_HTTP) {
4291 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4292 file, linenum, args[cur_arg + 1]);
4293 err_code |= ERR_ALERT;
4294 }
4295 newsrv->observe = HANA_OBS_LAYER7;
4296 }
4297 else {
4298 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004299 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004300 file, linenum, args[cur_arg], args[cur_arg + 1]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304
4305 cur_arg += 2;
4306 }
4307 else if (!strcmp(args[cur_arg], "on-error")) {
4308 if (!strcmp(args[cur_arg + 1], "fastinter"))
4309 newsrv->onerror = HANA_ONERR_FASTINTER;
4310 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4311 newsrv->onerror = HANA_ONERR_FAILCHK;
4312 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4313 newsrv->onerror = HANA_ONERR_SUDDTH;
4314 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4315 newsrv->onerror = HANA_ONERR_MARKDWN;
4316 else {
4317 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004318 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004319 file, linenum, args[cur_arg], args[cur_arg + 1]);
4320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
4322 }
4323
4324 cur_arg += 2;
4325 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004326 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4327 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4328 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4329 else {
4330 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4331 file, linenum, args[cur_arg], args[cur_arg + 1]);
4332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335
4336 cur_arg += 2;
4337 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004338 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4339 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4340 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4341 else {
4342 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4343 file, linenum, args[cur_arg], args[cur_arg + 1]);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347
4348 cur_arg += 2;
4349 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004350 else if (!strcmp(args[cur_arg], "error-limit")) {
4351 if (!*args[cur_arg + 1]) {
4352 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4353 file, linenum, args[cur_arg]);
4354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
4356 }
4357
4358 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4359
4360 if (newsrv->consecutive_errors_limit <= 0) {
4361 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4362 file, linenum, args[cur_arg]);
4363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
4365 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004366 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004367 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004368 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004369 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004370 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004371
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004373#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004374 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004375 file, linenum, "source", "usesrc");
4376#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004377 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004379#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004380 err_code |= ERR_ALERT | ERR_FATAL;
4381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 }
4383 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004384 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4385 if (!sk) {
4386 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
4389 }
4390 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004391
4392 if (port_low != port_high) {
4393 int i;
4394 if (port_low <= 0 || port_low > 65535 ||
4395 port_high <= 0 || port_high > 65535 ||
4396 port_low > port_high) {
4397 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4398 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004401 }
4402 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4403 for (i = 0; i < newsrv->sport_range->size; i++)
4404 newsrv->sport_range->ports[i] = port_low + i;
4405 }
4406
Willy Tarreaubaaee002006-06-26 02:48:02 +02004407 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004408 while (*(args[cur_arg])) {
4409 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004410#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4411#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004412 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4413 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4414 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004418#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004419 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004420 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004421 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004424 }
4425 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004426 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004427 newsrv->state |= SRV_TPROXY_CLI;
4428 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004429 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004431 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4432 char *name, *end;
4433
4434 name = args[cur_arg+1] + 7;
4435 while (isspace(*name))
4436 name++;
4437
4438 end = name;
4439 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4440 end++;
4441
4442 newsrv->state &= ~SRV_TPROXY_MASK;
4443 newsrv->state |= SRV_TPROXY_DYN;
4444 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4445 newsrv->bind_hdr_len = end - name;
4446 memcpy(newsrv->bind_hdr_name, name, end - name);
4447 newsrv->bind_hdr_name[end-name] = '\0';
4448 newsrv->bind_hdr_occ = -1;
4449
4450 /* now look for an occurrence number */
4451 while (isspace(*end))
4452 end++;
4453 if (*end == ',') {
4454 end++;
4455 name = end;
4456 if (*end == '-')
4457 end++;
4458 while (isdigit(*end))
4459 end++;
4460 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4461 }
4462
4463 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4464 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4465 " occurrences values smaller than %d.\n",
4466 file, linenum, MAX_HDR_HISTORY);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004470 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004471 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004472 if (!sk) {
4473 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
4476 }
4477 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004478 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004479 }
4480 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004481#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004482 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004483#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 cur_arg += 2;
4485 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004486#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004488 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004491#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4492 } /* "usesrc" */
4493
4494 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4495#ifdef SO_BINDTODEVICE
4496 if (!*args[cur_arg + 1]) {
4497 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004501 }
4502 if (newsrv->iface_name)
4503 free(newsrv->iface_name);
4504
4505 newsrv->iface_name = strdup(args[cur_arg + 1]);
4506 newsrv->iface_len = strlen(newsrv->iface_name);
4507 global.last_checks |= LSTCHK_NETADM;
4508#else
4509 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4510 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004511 err_code |= ERR_ALERT | ERR_FATAL;
4512 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004513#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004514 cur_arg += 2;
4515 continue;
4516 }
4517 /* this keyword in not an option of "source" */
4518 break;
4519 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004521 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004522 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4523 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004528 static int srv_dumped;
4529 struct srv_kw *kw;
4530 char *err;
4531
4532 kw = srv_find_kw(args[cur_arg]);
4533 if (kw) {
4534 char *err = NULL;
4535 int code;
4536
4537 if (!kw->parse) {
4538 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4539 file, linenum, args[0], args[1], args[cur_arg]);
4540 cur_arg += 1 + kw->skip ;
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
4544
4545 if (defsrv && !kw->default_ok) {
4546 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4547 file, linenum, args[0], args[1], args[cur_arg]);
4548 cur_arg += 1 + kw->skip ;
4549 err_code |= ERR_ALERT;
4550 continue;
4551 }
4552
4553 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4554 err_code |= code;
4555
4556 if (code) {
4557 if (err && *err) {
4558 indent_msg(&err, 2);
4559 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4560 }
4561 else
4562 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4563 file, linenum, args[0], args[1], args[cur_arg]);
4564 if (code & ERR_FATAL) {
4565 free(err);
4566 cur_arg += 1 + kw->skip;
4567 goto out;
4568 }
4569 }
4570 free(err);
4571 cur_arg += 1 + kw->skip;
4572 continue;
4573 }
4574
4575 err = NULL;
4576 if (!srv_dumped) {
4577 srv_dump_kws(&err);
4578 indent_msg(&err, 4);
4579 srv_dumped = 1;
4580 }
4581
4582 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4583 file, linenum, args[0], args[1], args[cur_arg],
4584 err ? " Registered keywords :" : "", err ? err : "");
4585 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004586
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
4590 }
4591
4592 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004593 if (newsrv->trackit) {
4594 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4595 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004598 }
4599
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004600 /* If neither a port nor an addr was specified and no check transport
4601 * layer is forced, then the transport layer used by the checks is the
4602 * same as for the production traffic. Otherwise we use raw_sock by
4603 * default, unless one is specified.
4604 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004605 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004606#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004607 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004608#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004609 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4610 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004611 /* try to get the port from check.addr if check.port not set */
4612 if (!newsrv->check.port)
4613 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004614
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004615 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4616 newsrv->check.port = realport; /* by default */
4617 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004618 /* not yet valid, because no port was set on
4619 * the server either. We'll check if we have
4620 * a known port on the first listener.
4621 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004622 struct listener *l;
4623
4624 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004625 newsrv->check.port = get_host_port(&l->addr);
4626 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004627 break;
4628 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004629 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004630 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4632 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_ALERT | ERR_FATAL;
4634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004636
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004637 /* Allocate buffer for check requests... */
4638 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004639 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4640 err_code |= ERR_ALERT | ERR_ABORT;
4641 goto out;
4642 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004643 newsrv->check.bi->size = global.tune.chksize;
4644
4645 /* Allocate buffer for check responses... */
4646 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4647 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4648 err_code |= ERR_ALERT | ERR_ABORT;
4649 goto out;
4650 }
4651 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004652
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004653 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004654 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004655 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4656 err_code |= ERR_ALERT | ERR_ABORT;
4657 goto out;
4658 }
4659
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004660 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4661 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 newsrv->state |= SRV_CHECKED;
4663 }
4664
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004665 if (!defsrv) {
4666 if (newsrv->state & SRV_BACKUP)
4667 curproxy->srv_bck++;
4668 else
4669 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004670
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004671 newsrv->prev_state = newsrv->state;
4672 }
William Lallemanda73203e2012-03-12 12:48:57 +01004673 }
4674
4675 else if (strcmp(args[0], "unique-id-format") == 0) {
4676 if (!*(args[1])) {
4677 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
4680 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004681 free(curproxy->uniqueid_format_string);
4682 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004683 }
William Lallemanda73203e2012-03-12 12:48:57 +01004684
4685 else if (strcmp(args[0], "unique-id-header") == 0) {
4686 if (!*(args[1])) {
4687 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
4691 free(curproxy->header_unique_id);
4692 curproxy->header_unique_id = strdup(args[1]);
4693 }
4694
William Lallemand723b73a2012-02-08 16:37:49 +01004695 else if (strcmp(args[0], "log-format") == 0) {
4696 if (!*(args[1])) {
4697 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004701
4702 if (curproxy->logformat_string != default_http_log_format &&
4703 curproxy->logformat_string != default_tcp_log_format &&
4704 curproxy->logformat_string != clf_http_log_format)
4705 free(curproxy->logformat_string);
4706 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
William Lallemand723b73a2012-02-08 16:37:49 +01004708
William Lallemand0f99e342011-10-12 17:50:54 +02004709 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4710 /* delete previous herited or defined syslog servers */
4711 struct logsrv *back;
4712
4713 if (*(args[1]) != 0) {
4714 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
4718
William Lallemand723b73a2012-02-08 16:37:49 +01004719 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4720 LIST_DEL(&tmplogsrv->list);
4721 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004722 }
4723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004725 struct logsrv *logsrv;
4726
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004728 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004729 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004730 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004731 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004732 LIST_INIT(&node->list);
4733 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004735 }
4736 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004737
4738 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739
William Lallemand0f99e342011-10-12 17:50:54 +02004740 logsrv->facility = get_log_facility(args[2]);
4741 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
4745
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
4747
William Lallemand0f99e342011-10-12 17:50:54 +02004748 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004750 logsrv->level = get_log_level(args[3]);
4751 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
4755
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 }
4758
William Lallemand0f99e342011-10-12 17:50:54 +02004759 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004760 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004761 logsrv->minlvl = get_log_level(args[4]);
4762 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004763 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
4766
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004767 }
4768 }
4769
Robert Tsai81ae1952007-12-05 10:47:29 +01004770 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004771 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004772 if (!sk) {
4773 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004774 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
William Lallemand0f99e342011-10-12 17:50:54 +02004778 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004779 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004780 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004781 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004782 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
William Lallemand0f99e342011-10-12 17:50:54 +02004786 logsrv->addr = *sk;
4787 if (!get_host_port(&logsrv->addr))
4788 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 }
William Lallemand0f99e342011-10-12 17:50:54 +02004790
4791 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
4793 else {
4794 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4795 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004798 }
4799 }
4800 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004801 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004802 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803
Willy Tarreau977b8e42006-12-29 14:19:17 +01004804 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004805 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004806
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004808 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4809 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004813
4814 /* we must first clear any optional default setting */
4815 curproxy->options &= ~PR_O_TPXY_MASK;
4816 free(curproxy->iface_name);
4817 curproxy->iface_name = NULL;
4818 curproxy->iface_len = 0;
4819
Willy Tarreaud5191e72010-02-09 20:50:45 +01004820 sk = str2sa(args[1]);
4821 if (!sk) {
4822 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
4826 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004828
4829 cur_arg = 2;
4830 while (*(args[cur_arg])) {
4831 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004832#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4833#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4835 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4836 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839 }
4840#endif
4841 if (!*args[cur_arg + 1]) {
4842 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4843 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004846 }
4847
4848 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004849 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004850 curproxy->options |= PR_O_TPXY_CLI;
4851 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004852 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004853 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004854 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4855 char *name, *end;
4856
4857 name = args[cur_arg+1] + 7;
4858 while (isspace(*name))
4859 name++;
4860
4861 end = name;
4862 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4863 end++;
4864
4865 curproxy->options &= ~PR_O_TPXY_MASK;
4866 curproxy->options |= PR_O_TPXY_DYN;
4867 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4868 curproxy->bind_hdr_len = end - name;
4869 memcpy(curproxy->bind_hdr_name, name, end - name);
4870 curproxy->bind_hdr_name[end-name] = '\0';
4871 curproxy->bind_hdr_occ = -1;
4872
4873 /* now look for an occurrence number */
4874 while (isspace(*end))
4875 end++;
4876 if (*end == ',') {
4877 end++;
4878 name = end;
4879 if (*end == '-')
4880 end++;
4881 while (isdigit(*end))
4882 end++;
4883 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4884 }
4885
4886 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4887 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4888 " occurrences values smaller than %d.\n",
4889 file, linenum, MAX_HDR_HISTORY);
4890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004893 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004894 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004895 if (!sk) {
4896 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
4899 }
4900 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004901 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902 }
4903 global.last_checks |= LSTCHK_NETADM;
4904#if !defined(CONFIG_HAP_LINUX_TPROXY)
4905 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004906#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004907#else /* no TPROXY support */
4908 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004909 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004912#endif
4913 cur_arg += 2;
4914 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004915 }
4916
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004917 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4918#ifdef SO_BINDTODEVICE
4919 if (!*args[cur_arg + 1]) {
4920 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004924 }
4925 if (curproxy->iface_name)
4926 free(curproxy->iface_name);
4927
4928 curproxy->iface_name = strdup(args[cur_arg + 1]);
4929 curproxy->iface_len = strlen(curproxy->iface_name);
4930 global.last_checks |= LSTCHK_NETADM;
4931#else
4932 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4933 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004936#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004937 cur_arg += 2;
4938 continue;
4939 }
4940 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02004941 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004946 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4947 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4948 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004951 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959
4960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004961 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004962 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004968 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004975 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004976 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004982 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004983 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004984 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004989 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004990 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004994 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004996 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005000 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005001 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005003 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005004 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005007 }
5008 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005010 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005011 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005012 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005013 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5018 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005022
5023 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005024 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005025 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005026 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005030 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005031 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005032 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005033 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 }
5036 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005037 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005038 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005039 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005040 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
5043 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005045 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005046 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005047 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
5050 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005052 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005053 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005054 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005056 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005057 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005059 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005060 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005061 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005062 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005065 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005066
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 if (curproxy == &defproxy) {
5068 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005069 err_code |= ERR_ALERT | ERR_FATAL;
5070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005072 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 if (*(args[1]) == 0) {
5076 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_ALERT | ERR_FATAL;
5078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005079 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005080
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005081 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005082 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5083 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5084 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5089 }
5090 else if (*args[2]) {
5091 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5092 file, linenum, args[0], args[2]);
5093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
5095 }
5096
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005097 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005098 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005099 wl->s = strdup(args[1]);
5100 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005101 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
5103 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005104 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005110
Willy Tarreauade5ec42010-01-28 19:33:49 +01005111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005112 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005113 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 }
5117 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005118 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005119 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005120 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005121 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 }
5124 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005125 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005126 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005127 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005128 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
5131 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005132 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005137 }
5138
Willy Tarreauade5ec42010-01-28 19:33:49 +01005139 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005140 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005141 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005144 }
5145 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005146 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005147 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005148 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005149 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
5152 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005153 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005154 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005155 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005158 }
5159 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005160 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005161
Willy Tarreaubaaee002006-06-26 02:48:02 +02005162 if (curproxy == &defproxy) {
5163 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005167 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005168 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169
Willy Tarreaubaaee002006-06-26 02:48:02 +02005170 if (*(args[1]) == 0) {
5171 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005174 }
5175
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005176 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005177 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5178 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5179 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183 err_code |= warnif_cond_requires_req(cond, file, linenum);
5184 }
5185 else if (*args[2]) {
5186 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5187 file, linenum, args[0], args[2]);
5188 err_code |= ERR_ALERT | ERR_FATAL;
5189 goto out;
5190 }
5191
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005192 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005193 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005194 wl->s = strdup(args[1]);
5195 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
5197 else if (!strcmp(args[0], "errorloc") ||
5198 !strcmp(args[0], "errorloc302") ||
5199 !strcmp(args[0], "errorloc303")) { /* error location */
5200 int errnum, errlen;
5201 char *err;
5202
Willy Tarreau977b8e42006-12-29 14:19:17 +01005203 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005205
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005207 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211
5212 errnum = atol(args[1]);
5213 if (!strcmp(args[0], "errorloc303")) {
5214 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5215 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5216 } else {
5217 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5218 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5219 }
5220
Willy Tarreau0f772532006-12-23 20:51:41 +01005221 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5222 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005223 chunk_destroy(&curproxy->errmsg[rc]);
5224 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005225 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005228
5229 if (rc >= HTTP_ERR_SIZE) {
5230 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5231 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 free(err);
5233 }
5234 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005235 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5236 int errnum, errlen, fd;
5237 char *err;
5238 struct stat stat;
5239
5240 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005241 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005242
5243 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005244 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005247 }
5248
5249 fd = open(args[2], O_RDONLY);
5250 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5251 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5252 file, linenum, args[2], args[1]);
5253 if (fd >= 0)
5254 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005257 }
5258
Willy Tarreau27a674e2009-08-17 07:23:33 +02005259 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005260 errlen = stat.st_size;
5261 } else {
5262 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005263 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005265 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005266 }
5267
5268 err = malloc(errlen); /* malloc() must succeed during parsing */
5269 errnum = read(fd, err, errlen);
5270 if (errnum != errlen) {
5271 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5272 file, linenum, args[2], args[1]);
5273 close(fd);
5274 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005277 }
5278 close(fd);
5279
5280 errnum = atol(args[1]);
5281 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5282 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005283 chunk_destroy(&curproxy->errmsg[rc]);
5284 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005285 break;
5286 }
5287 }
5288
5289 if (rc >= HTTP_ERR_SIZE) {
5290 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5291 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005292 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005293 free(err);
5294 }
5295 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005296 else if (!strcmp(args[0], "compression")) {
5297 struct comp *comp;
5298 if (curproxy->comp == NULL) {
5299 comp = calloc(1, sizeof(struct comp));
5300 curproxy->comp = comp;
5301 } else {
5302 comp = curproxy->comp;
5303 }
5304
5305 if (!strcmp(args[1], "algo")) {
5306 int cur_arg;
William Lallemand552df672012-11-07 13:21:47 +01005307 struct comp_ctx ctx;
5308
William Lallemand82fe75c2012-10-23 10:25:10 +02005309 cur_arg = 2;
5310 if (!*args[cur_arg]) {
5311 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5312 file, linenum, args[0]);
5313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
5315 }
5316 while (*(args[cur_arg])) {
5317 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5318 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5319 file, linenum, args[0], args[cur_arg]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
William Lallemand552df672012-11-07 13:21:47 +01005323 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5324 curproxy->comp->algos->end(&ctx);
5325 } else {
5326 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5327 file, linenum, args[0], args[cur_arg]);
5328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
5330 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005331 cur_arg ++;
5332 continue;
5333 }
5334 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005335 else if (!strcmp(args[1], "offload")) {
5336 comp->offload = 1;
5337 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005338 else if (!strcmp(args[1], "type")) {
5339 int cur_arg;
5340 cur_arg = 2;
5341 if (!*args[cur_arg]) {
5342 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5343 file, linenum, args[0]);
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347 while (*(args[cur_arg])) {
5348 comp_append_type(comp, args[cur_arg]);
5349 cur_arg ++;
5350 continue;
5351 }
5352 }
5353 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005354 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005355 file, linenum, args[0]);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005361 struct cfg_kw_list *kwl;
5362 int index;
5363
5364 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5365 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5366 if (kwl->kw[index].section != CFG_LISTEN)
5367 continue;
5368 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5369 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005370 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005371 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005372 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005373 err_code |= ERR_ALERT | ERR_FATAL;
5374 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005375 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005376 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005377 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005378 err_code |= ERR_WARN;
5379 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005380 }
Willy Tarreau93893792009-07-23 13:19:11 +02005381 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005382 }
5383 }
5384 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005385
Willy Tarreau6daf3432008-01-22 16:44:08 +01005386 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
Willy Tarreau93893792009-07-23 13:19:11 +02005390 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005391 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005392 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393}
5394
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005395int
5396cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5397{
5398
5399 int err_code = 0;
5400 const char *err;
5401
5402 if (!strcmp(args[0], "userlist")) { /* new userlist */
5403 struct userlist *newul;
5404
5405 if (!*args[1]) {
5406 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5407 file, linenum, args[0]);
5408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
5411
5412 err = invalid_char(args[1]);
5413 if (err) {
5414 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5415 file, linenum, *err, args[0], args[1]);
5416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
5418 }
5419
5420 for (newul = userlist; newul; newul = newul->next)
5421 if (!strcmp(newul->name, args[1])) {
5422 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5423 file, linenum, args[1]);
5424 err_code |= ERR_WARN;
5425 goto out;
5426 }
5427
5428 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5429 if (!newul) {
5430 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5431 err_code |= ERR_ALERT | ERR_ABORT;
5432 goto out;
5433 }
5434
5435 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5436 newul->name = strdup(args[1]);
5437
5438 if (!newul->groupusers | !newul->name) {
5439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5440 err_code |= ERR_ALERT | ERR_ABORT;
5441 goto out;
5442 }
5443
5444 newul->next = userlist;
5445 userlist = newul;
5446
5447 } else if (!strcmp(args[0], "group")) { /* new group */
5448 int cur_arg, i;
5449 const char *err;
5450
5451 if (!*args[1]) {
5452 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5453 file, linenum, args[0]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
5457
5458 err = invalid_char(args[1]);
5459 if (err) {
5460 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5461 file, linenum, *err, args[0], args[1]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465
5466 for(i = 0; i < userlist->grpcnt; i++)
5467 if (!strcmp(userlist->groups[i], args[1])) {
5468 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5469 file, linenum, args[1], userlist->name);
5470 err_code |= ERR_ALERT;
5471 goto out;
5472 }
5473
5474 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5475 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5476 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480
5481 cur_arg = 2;
5482
5483 while (*args[cur_arg]) {
5484 if (!strcmp(args[cur_arg], "users")) {
5485 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5486 cur_arg += 2;
5487 continue;
5488 } else {
5489 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5490 file, linenum, args[0]);
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 goto out;
5493 }
5494 }
5495
5496 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5497 } else if (!strcmp(args[0], "user")) { /* new user */
5498 struct auth_users *newuser;
5499 int cur_arg;
5500
5501 if (!*args[1]) {
5502 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5503 file, linenum, args[0]);
5504 err_code |= ERR_ALERT | ERR_FATAL;
5505 goto out;
5506 }
5507
5508 for (newuser = userlist->users; newuser; newuser = newuser->next)
5509 if (!strcmp(newuser->user, args[1])) {
5510 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5511 file, linenum, args[1], userlist->name);
5512 err_code |= ERR_ALERT;
5513 goto out;
5514 }
5515
5516 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5517 if (!newuser) {
5518 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5519 err_code |= ERR_ALERT | ERR_ABORT;
5520 goto out;
5521 }
5522
5523 newuser->user = strdup(args[1]);
5524
5525 newuser->next = userlist->users;
5526 userlist->users = newuser;
5527
5528 cur_arg = 2;
5529
5530 while (*args[cur_arg]) {
5531 if (!strcmp(args[cur_arg], "password")) {
5532#ifndef CONFIG_HAP_CRYPT
5533 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5534 file, linenum);
5535 err_code |= ERR_ALERT;
5536#endif
5537 newuser->pass = strdup(args[cur_arg + 1]);
5538 cur_arg += 2;
5539 continue;
5540 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5541 newuser->pass = strdup(args[cur_arg + 1]);
5542 newuser->flags |= AU_O_INSECURE;
5543 cur_arg += 2;
5544 continue;
5545 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005546 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005547 cur_arg += 2;
5548 continue;
5549 } else {
5550 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5551 file, linenum, args[0]);
5552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
5554 }
5555 }
5556 } else {
5557 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5558 err_code |= ERR_ALERT | ERR_FATAL;
5559 }
5560
5561out:
5562 return err_code;
5563}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564
5565/*
5566 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005567 * Returns the error code, 0 if OK, or any combination of :
5568 * - ERR_ABORT: must abort ASAP
5569 * - ERR_FATAL: we can continue parsing but not start the service
5570 * - ERR_WARN: a warning has been emitted
5571 * - ERR_ALERT: an alert has been emitted
5572 * Only the two first ones can stop processing, the two others are just
5573 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005575int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005577 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 FILE *f;
5579 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005581 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 if ((f=fopen(file,"r")) == NULL)
5584 return -1;
5585
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005586 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005587 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005588 char *end;
5589 char *args[MAX_LINE_ARGS + 1];
5590 char *line = thisline;
5591
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 linenum++;
5593
5594 end = line + strlen(line);
5595
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005596 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5597 /* Check if we reached the limit and the last char is not \n.
5598 * Watch out for the last line without the terminating '\n'!
5599 */
5600 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005601 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005602 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005603 }
5604
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005606 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 line++;
5608
5609 arg = 0;
5610 args[arg] = line;
5611
5612 while (*line && arg < MAX_LINE_ARGS) {
5613 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5614 * C equivalent value. Other combinations left unchanged (eg: \1).
5615 */
5616 if (*line == '\\') {
5617 int skip = 0;
5618 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5619 *line = line[1];
5620 skip = 1;
5621 }
5622 else if (line[1] == 'r') {
5623 *line = '\r';
5624 skip = 1;
5625 }
5626 else if (line[1] == 'n') {
5627 *line = '\n';
5628 skip = 1;
5629 }
5630 else if (line[1] == 't') {
5631 *line = '\t';
5632 skip = 1;
5633 }
5634 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005635 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 unsigned char hex1, hex2;
5637 hex1 = toupper(line[2]) - '0';
5638 hex2 = toupper(line[3]) - '0';
5639 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5640 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5641 *line = (hex1<<4) + hex2;
5642 skip = 3;
5643 }
5644 else {
5645 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005646 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 }
5648 }
5649 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005650 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 end -= skip;
5652 }
5653 line++;
5654 }
5655 else if (*line == '#' || *line == '\n' || *line == '\r') {
5656 /* end of string, end of loop */
5657 *line = 0;
5658 break;
5659 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005660 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005662 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005663 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 line++;
5665 args[++arg] = line;
5666 }
5667 else {
5668 line++;
5669 }
5670 }
5671
5672 /* empty line */
5673 if (!**args)
5674 continue;
5675
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005676 if (*line) {
5677 /* we had to stop due to too many args.
5678 * Let's terminate the string, print the offending part then cut the
5679 * last arg.
5680 */
5681 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5682 line++;
5683 *line = '\0';
5684
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005685 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005686 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 args[arg] = line;
5689 }
5690
Willy Tarreau540abe42007-05-02 20:50:16 +02005691 /* zero out remaining args and ensure that at least one entry
5692 * is zeroed out.
5693 */
5694 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 args[arg] = line;
5696 }
5697
Willy Tarreau3842f002009-06-14 11:39:52 +02005698 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005699 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005700 char *tmp;
5701
Willy Tarreau3842f002009-06-14 11:39:52 +02005702 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005703 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005704 for (arg=0; *args[arg+1]; arg++)
5705 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005706 *tmp = '\0'; // fix the next arg to \0
5707 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005708 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005709 else if (!strcmp(args[0], "default")) {
5710 kwm = KWM_DEF;
5711 for (arg=0; *args[arg+1]; arg++)
5712 args[arg] = args[arg+1]; // shift args after inversion
5713 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005714
William Lallemand0f99e342011-10-12 17:50:54 +02005715 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5716 strcmp(args[0], "log") != 0) {
5717 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005719 }
5720
Willy Tarreau977b8e42006-12-29 14:19:17 +01005721 if (!strcmp(args[0], "listen") ||
5722 !strcmp(args[0], "frontend") ||
5723 !strcmp(args[0], "backend") ||
5724 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005725 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005727 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005728 cursection = strdup(args[0]);
5729 }
5730 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005732 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005733 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005734 }
5735 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005736 confsect = CFG_USERLIST;
5737 free(cursection);
5738 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005739 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005740 else if (!strcmp(args[0], "peers")) {
5741 confsect = CFG_PEERS;
5742 free(cursection);
5743 cursection = strdup(args[0]);
5744 }
5745
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 /* else it's a section keyword */
5747
5748 switch (confsect) {
5749 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 break;
5752 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005753 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005755 case CFG_USERLIST:
5756 err_code |= cfg_parse_users(file, linenum, args, kwm);
5757 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005758 case CFG_PEERS:
5759 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5760 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005762 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005763 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005765
5766 if (err_code & ERR_ABORT)
5767 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005769 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005770 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005772 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005773}
5774
Willy Tarreaubb925012009-07-23 13:36:36 +02005775/*
5776 * Returns the error code, 0 if OK, or any combination of :
5777 * - ERR_ABORT: must abort ASAP
5778 * - ERR_FATAL: we can continue parsing but not start the service
5779 * - ERR_WARN: a warning has been emitted
5780 * - ERR_ALERT: an alert has been emitted
5781 * Only the two first ones can stop processing, the two others are just
5782 * indicators.
5783 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005784int check_config_validity()
5785{
5786 int cfgerr = 0;
5787 struct proxy *curproxy = NULL;
5788 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005789 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005790 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005791 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005792 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005793
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005794 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 /*
5796 * Now, check for the integrity of all that we have collected.
5797 */
5798
5799 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005800 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005801
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005802 /* first, we will invert the proxy list order */
5803 curproxy = NULL;
5804 while (proxy) {
5805 struct proxy *next;
5806
5807 next = proxy->next;
5808 proxy->next = curproxy;
5809 curproxy = proxy;
5810 if (!next)
5811 break;
5812 proxy = next;
5813 }
5814
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005816 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005817 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005818 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005819 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005820 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005821 unsigned int next_id;
5822
Willy Tarreau050536d2012-10-04 08:47:34 +02005823 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005824 /* proxy ID not set, use automatic numbering with first
5825 * spare entry starting with next_pxid.
5826 */
5827 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5828 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5829 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005830 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005831 next_pxid++;
5832
Willy Tarreau55ea7572007-06-17 19:56:27 +02005833
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005835 /* ensure we don't keep listeners uselessly bound */
5836 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 curproxy = curproxy->next;
5838 continue;
5839 }
5840
Willy Tarreauff01a212009-03-15 13:46:16 +01005841 switch (curproxy->mode) {
5842 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005843 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005844 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005845 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5846 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005847 cfgerr++;
5848 }
5849
5850 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005851 Warning("config : servers will be ignored for %s '%s'.\n",
5852 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005853 break;
5854
5855 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005856 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005857 break;
5858
5859 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005860 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005861 break;
5862 }
5863
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005864 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005865 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005866 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005867 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5868 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005869 cfgerr++;
5870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005871#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005872 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005873 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5874 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005875 cfgerr++;
5876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005878 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005879 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5880 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005881 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005882 }
5883 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005884 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005885 /* If no LB algo is set in a backend, and we're not in
5886 * transparent mode, dispatch mode nor proxy mode, we
5887 * want to use balance roundrobin by default.
5888 */
5889 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5890 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
5892 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005893
Willy Tarreau1620ec32011-08-06 17:05:02 +02005894 if (curproxy->options & PR_O_DISPATCH)
5895 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5896 else if (curproxy->options & PR_O_HTTP_PROXY)
5897 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5898 else if (curproxy->options & PR_O_TRANSP)
5899 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005900
Willy Tarreau1620ec32011-08-06 17:05:02 +02005901 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5902 if (curproxy->options & PR_O_DISABLE404) {
5903 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5904 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5905 err_code |= ERR_WARN;
5906 curproxy->options &= ~PR_O_DISABLE404;
5907 }
5908 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5909 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5910 "send-state", proxy_type_str(curproxy), curproxy->id);
5911 err_code |= ERR_WARN;
5912 curproxy->options &= ~PR_O2_CHK_SNDST;
5913 }
Willy Tarreauef781042010-01-27 11:53:01 +01005914 }
5915
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005916 /* if a default backend was specified, let's find it */
5917 if (curproxy->defbe.name) {
5918 struct proxy *target;
5919
Alex Williams96532db2009-11-01 21:27:13 -05005920 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005921 if (!target) {
5922 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5923 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005924 cfgerr++;
5925 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005926 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5927 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005928 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005929 } else {
5930 free(curproxy->defbe.name);
5931 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005932 /* we force the backend to be present on at least all of
5933 * the frontend's processes.
5934 */
5935 target->bind_proc = curproxy->bind_proc ?
5936 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005937
5938 /* Emit a warning if this proxy also has some servers */
5939 if (curproxy->srv) {
5940 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5941 curproxy->id);
5942 err_code |= ERR_WARN;
5943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
5945 }
5946
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005947 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005948 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5949 /* map jump target for ACT_SETBE in req_rep chain */
5950 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005951 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005952 struct proxy *target;
5953
Willy Tarreaua496b602006-12-17 23:15:24 +01005954 if (exp->action != ACT_SETBE)
5955 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005956
Alex Williams96532db2009-11-01 21:27:13 -05005957 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005958 if (!target) {
5959 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5960 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005961 cfgerr++;
5962 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005963 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5964 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005965 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005966 } else {
5967 free((void *)exp->replace);
5968 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005969 /* we force the backend to be present on at least all of
5970 * the frontend's processes.
5971 */
5972 target->bind_proc = curproxy->bind_proc ?
5973 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005974 }
5975 }
5976 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005977
5978 /* find the target proxy for 'use_backend' rules */
5979 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005980 struct proxy *target;
5981
Alex Williams96532db2009-11-01 21:27:13 -05005982 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005983
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005984 if (!target) {
5985 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5986 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005987 cfgerr++;
5988 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005989 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5990 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005991 cfgerr++;
5992 } else {
5993 free((void *)rule->be.name);
5994 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005995 /* we force the backend to be present on at least all of
5996 * the frontend's processes.
5997 */
5998 target->bind_proc = curproxy->bind_proc ?
5999 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006000 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006001 }
6002
6003 /* find the target proxy for 'use_backend' rules */
6004 list_for_each_entry(srule, &curproxy->server_rules, list) {
6005 struct server *target = findserver(curproxy, srule->srv.name);
6006
6007 if (!target) {
6008 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6009 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6010 cfgerr++;
6011 continue;
6012 }
6013 free((void *)srule->srv.name);
6014 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006015 }
6016
Emeric Brunb982a3d2010-01-04 15:45:53 +01006017 /* find the target table for 'stick' rules */
6018 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6019 struct proxy *target;
6020
Emeric Brun1d33b292010-01-04 15:47:17 +01006021 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6022 if (mrule->flags & STK_IS_STORE)
6023 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6024
Emeric Brunb982a3d2010-01-04 15:45:53 +01006025 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006026 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006027 else
6028 target = curproxy;
6029
6030 if (!target) {
6031 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6032 curproxy->id, mrule->table.name);
6033 cfgerr++;
6034 }
6035 else if (target->table.size == 0) {
6036 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6037 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6038 cfgerr++;
6039 }
Willy Tarreau12785782012-04-27 21:37:17 +02006040 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6041 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006042 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6043 cfgerr++;
6044 }
6045 else {
6046 free((void *)mrule->table.name);
6047 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006048 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006049 }
6050 }
6051
6052 /* find the target table for 'store response' rules */
6053 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6054 struct proxy *target;
6055
Emeric Brun1d33b292010-01-04 15:47:17 +01006056 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6057
Emeric Brunb982a3d2010-01-04 15:45:53 +01006058 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006059 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006060 else
6061 target = curproxy;
6062
6063 if (!target) {
6064 Alert("Proxy '%s': unable to find store table '%s'.\n",
6065 curproxy->id, mrule->table.name);
6066 cfgerr++;
6067 }
6068 else if (target->table.size == 0) {
6069 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6070 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6071 cfgerr++;
6072 }
Willy Tarreau12785782012-04-27 21:37:17 +02006073 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6074 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006075 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6076 cfgerr++;
6077 }
6078 else {
6079 free((void *)mrule->table.name);
6080 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006081 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006082 }
6083 }
6084
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006085 /* find the target table for 'tcp-request' layer 4 rules */
6086 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6087 struct proxy *target;
6088
Willy Tarreau56123282010-08-06 19:06:56 +02006089 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006090 continue;
6091
6092 if (trule->act_prm.trk_ctr.table.n)
6093 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6094 else
6095 target = curproxy;
6096
6097 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006098 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6099 curproxy->id, trule->act_prm.trk_ctr.table.n,
6100 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006101 cfgerr++;
6102 }
6103 else if (target->table.size == 0) {
6104 Alert("Proxy '%s': table '%s' used but not configured.\n",
6105 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6106 cfgerr++;
6107 }
6108 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006109 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 +02006110 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6111 cfgerr++;
6112 }
6113 else {
6114 free(trule->act_prm.trk_ctr.table.n);
6115 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006116 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006117 * to pass a list of counters to track and allocate them right here using
6118 * stktable_alloc_data_type().
6119 */
6120 }
6121 }
6122
Willy Tarreaud1f96522010-08-03 19:34:32 +02006123 /* find the target table for 'tcp-request' layer 6 rules */
6124 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6125 struct proxy *target;
6126
Willy Tarreau56123282010-08-06 19:06:56 +02006127 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006128 continue;
6129
6130 if (trule->act_prm.trk_ctr.table.n)
6131 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6132 else
6133 target = curproxy;
6134
6135 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006136 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6137 curproxy->id, trule->act_prm.trk_ctr.table.n,
6138 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006139 cfgerr++;
6140 }
6141 else if (target->table.size == 0) {
6142 Alert("Proxy '%s': table '%s' used but not configured.\n",
6143 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6144 cfgerr++;
6145 }
6146 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006147 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 +02006148 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6149 cfgerr++;
6150 }
6151 else {
6152 free(trule->act_prm.trk_ctr.table.n);
6153 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006154 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006155 * to pass a list of counters to track and allocate them right here using
6156 * stktable_alloc_data_type().
6157 */
6158 }
6159 }
6160
Emeric Brun32da3c42010-09-23 18:39:19 +02006161 if (curproxy->table.peers.name) {
6162 struct peers *curpeers = peers;
6163
6164 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6165 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6166 free((void *)curproxy->table.peers.name);
6167 curproxy->table.peers.p = peers;
6168 break;
6169 }
6170 }
6171
6172 if (!curpeers) {
6173 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6174 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006175 free((void *)curproxy->table.peers.name);
6176 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006177 cfgerr++;
6178 }
6179 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006180 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6181 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006182 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006183 cfgerr++;
6184 }
6185 }
6186
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006187 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006188 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006189 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6190 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6191 "proxy", curproxy->id);
6192 cfgerr++;
6193 goto out_uri_auth_compat;
6194 }
6195
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006196 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006197 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006198 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006199 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006200
Willy Tarreau95fa4692010-02-01 13:05:50 +01006201 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6202 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006203
6204 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006205 uri_auth_compat_req[i++] = "realm";
6206 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6207 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006208
Willy Tarreau95fa4692010-02-01 13:05:50 +01006209 uri_auth_compat_req[i++] = "unless";
6210 uri_auth_compat_req[i++] = "{";
6211 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6212 uri_auth_compat_req[i++] = "}";
6213 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006214
Willy Tarreauff011f22011-01-06 17:51:27 +01006215 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6216 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006217 cfgerr++;
6218 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006219 }
6220
Willy Tarreauff011f22011-01-06 17:51:27 +01006221 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006222
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006223 if (curproxy->uri_auth->auth_realm) {
6224 free(curproxy->uri_auth->auth_realm);
6225 curproxy->uri_auth->auth_realm = NULL;
6226 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006227
6228 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006229 }
6230out_uri_auth_compat:
6231
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006232 cfgerr += acl_find_targets(curproxy);
6233
Willy Tarreau2738a142006-07-08 17:28:09 +02006234 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006235 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006236 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006237 (!curproxy->timeout.connect ||
6238 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006239 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006240 " | While not properly invalid, you will certainly encounter various problems\n"
6241 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006242 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006243 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006244 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006245 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006246
Willy Tarreau1fa31262007-12-03 00:36:16 +01006247 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6248 * We must still support older configurations, so let's find out whether those
6249 * parameters have been set or must be copied from contimeouts.
6250 */
6251 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006252 if (!curproxy->timeout.tarpit ||
6253 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006254 /* tarpit timeout not set. We search in the following order:
6255 * default.tarpit, curr.connect, default.connect.
6256 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006257 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006258 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006259 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006260 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006261 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006262 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006263 }
6264 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006265 (!curproxy->timeout.queue ||
6266 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006267 /* queue timeout not set. We search in the following order:
6268 * default.queue, curr.connect, default.connect.
6269 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006270 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006271 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006272 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006273 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006274 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006275 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006276 }
6277 }
6278
Willy Tarreau1620ec32011-08-06 17:05:02 +02006279 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006280 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6281 curproxy->check_req = (char *)malloc(curproxy->check_len);
6282 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006283 }
6284
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006285 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006286 if (curproxy->nb_req_cap) {
6287 if (curproxy->mode == PR_MODE_HTTP) {
6288 curproxy->req_cap_pool = create_pool("ptrcap",
6289 curproxy->nb_req_cap * sizeof(char *),
6290 MEM_F_SHARED);
6291 } else {
6292 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6293 proxy_type_str(curproxy), curproxy->id);
6294 err_code |= ERR_WARN;
6295 curproxy->to_log &= ~LW_REQHDR;
6296 curproxy->nb_req_cap = 0;
6297 }
6298 }
6299
6300 if (curproxy->nb_rsp_cap) {
6301 if (curproxy->mode == PR_MODE_HTTP) {
6302 curproxy->rsp_cap_pool = create_pool("ptrcap",
6303 curproxy->nb_rsp_cap * sizeof(char *),
6304 MEM_F_SHARED);
6305 } else {
6306 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6307 proxy_type_str(curproxy), curproxy->id);
6308 err_code |= ERR_WARN;
6309 curproxy->to_log &= ~LW_REQHDR;
6310 curproxy->nb_rsp_cap = 0;
6311 }
6312 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006313
Willy Tarreau196729e2012-05-31 19:30:26 +02006314 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006315 if (!(curproxy->cap & PR_CAP_FE)) {
6316 if (curproxy->logformat_string != default_http_log_format &&
6317 curproxy->logformat_string != default_tcp_log_format &&
6318 curproxy->logformat_string != clf_http_log_format)
6319 free(curproxy->logformat_string);
6320 curproxy->logformat_string = NULL;
6321 }
6322
Willy Tarreau196729e2012-05-31 19:30:26 +02006323 if (curproxy->logformat_string)
6324 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6325
6326 if (curproxy->uniqueid_format_string)
6327 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6328
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 /* first, we will invert the servers list order */
6330 newsrv = NULL;
6331 while (curproxy->srv) {
6332 struct server *next;
6333
6334 next = curproxy->srv->next;
6335 curproxy->srv->next = newsrv;
6336 newsrv = curproxy->srv;
6337 if (!next)
6338 break;
6339 curproxy->srv = next;
6340 }
6341
Willy Tarreaudd701652010-05-25 23:03:02 +02006342 /* assign automatic UIDs to servers which don't have one yet */
6343 next_id = 1;
6344 newsrv = curproxy->srv;
6345 while (newsrv != NULL) {
6346 if (!newsrv->puid) {
6347 /* server ID not set, use automatic numbering with first
6348 * spare entry starting with next_svid.
6349 */
6350 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6351 newsrv->conf.id.key = newsrv->puid = next_id;
6352 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6353 }
6354 next_id++;
6355 newsrv = newsrv->next;
6356 }
6357
Willy Tarreau20697042007-11-15 23:26:18 +01006358 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006359 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360
Willy Tarreau62c3be22012-01-20 13:12:32 +01006361 /*
6362 * If this server supports a maxconn parameter, it needs a dedicated
6363 * tasks to fill the emptied slots when a connection leaves.
6364 * Also, resolve deferred tracking dependency if needed.
6365 */
6366 newsrv = curproxy->srv;
6367 while (newsrv != NULL) {
6368 if (newsrv->minconn > newsrv->maxconn) {
6369 /* Only 'minconn' was specified, or it was higher than or equal
6370 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6371 * this will avoid further useless expensive computations.
6372 */
6373 newsrv->maxconn = newsrv->minconn;
6374 } else if (newsrv->maxconn && !newsrv->minconn) {
6375 /* minconn was not specified, so we set it to maxconn */
6376 newsrv->minconn = newsrv->maxconn;
6377 }
6378
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006379#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006380 if (newsrv->use_ssl || newsrv->check.use_ssl)
6381 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006382#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006383
Willy Tarreau62c3be22012-01-20 13:12:32 +01006384 if (newsrv->trackit) {
6385 struct proxy *px;
6386 struct server *srv;
6387 char *pname, *sname;
6388
6389 pname = newsrv->trackit;
6390 sname = strrchr(pname, '/');
6391
6392 if (sname)
6393 *sname++ = '\0';
6394 else {
6395 sname = pname;
6396 pname = NULL;
6397 }
6398
6399 if (pname) {
6400 px = findproxy(pname, PR_CAP_BE);
6401 if (!px) {
6402 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6403 proxy_type_str(curproxy), curproxy->id,
6404 newsrv->id, pname);
6405 cfgerr++;
6406 goto next_srv;
6407 }
6408 } else
6409 px = curproxy;
6410
6411 srv = findserver(px, sname);
6412 if (!srv) {
6413 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6414 proxy_type_str(curproxy), curproxy->id,
6415 newsrv->id, sname);
6416 cfgerr++;
6417 goto next_srv;
6418 }
6419
6420 if (!(srv->state & SRV_CHECKED)) {
6421 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6422 "tracking as it does not have checks enabled.\n",
6423 proxy_type_str(curproxy), curproxy->id,
6424 newsrv->id, px->id, srv->id);
6425 cfgerr++;
6426 goto next_srv;
6427 }
6428
6429 if (curproxy != px &&
6430 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6431 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6432 "tracking: disable-on-404 option inconsistency.\n",
6433 proxy_type_str(curproxy), curproxy->id,
6434 newsrv->id, px->id, srv->id);
6435 cfgerr++;
6436 goto next_srv;
6437 }
6438
6439 /* if the other server is forced disabled, we have to do the same here */
6440 if (srv->state & SRV_MAINTAIN) {
6441 newsrv->state |= SRV_MAINTAIN;
6442 newsrv->state &= ~SRV_RUNNING;
6443 newsrv->health = 0;
6444 }
6445
6446 newsrv->track = srv;
6447 newsrv->tracknext = srv->tracknext;
6448 srv->tracknext = newsrv;
6449
6450 free(newsrv->trackit);
6451 newsrv->trackit = NULL;
6452 }
6453 next_srv:
6454 newsrv = newsrv->next;
6455 }
6456
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006457 /* We have to initialize the server lookup mechanism depending
6458 * on what LB algorithm was choosen.
6459 */
6460
6461 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6462 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6463 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006464 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6465 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6466 init_server_map(curproxy);
6467 } else {
6468 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6469 fwrr_init_server_groups(curproxy);
6470 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006471 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006472
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006473 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006474 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6475 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6476 fwlc_init_server_tree(curproxy);
6477 } else {
6478 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6479 fas_init_server_tree(curproxy);
6480 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006481 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006482
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006483 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006484 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6485 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6486 chash_init_server_tree(curproxy);
6487 } else {
6488 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6489 init_server_map(curproxy);
6490 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006491 break;
6492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006493
6494 if (curproxy->options & PR_O_LOGASAP)
6495 curproxy->to_log &= ~LW_BYTES;
6496
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006497 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006498 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006499 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6500 proxy_type_str(curproxy), curproxy->id);
6501 err_code |= ERR_WARN;
6502 }
6503
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006504 if (curproxy->mode != PR_MODE_HTTP) {
6505 int optnum;
6506
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006507 if (curproxy->uri_auth) {
6508 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6509 proxy_type_str(curproxy), curproxy->id);
6510 err_code |= ERR_WARN;
6511 curproxy->uri_auth = NULL;
6512 }
6513
Willy Tarreau87cf5142011-08-19 22:57:24 +02006514 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006515 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6516 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6517 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006518 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006519 }
6520
6521 if (curproxy->options & PR_O_ORGTO) {
6522 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6523 "originalto", proxy_type_str(curproxy), curproxy->id);
6524 err_code |= ERR_WARN;
6525 curproxy->options &= ~PR_O_ORGTO;
6526 }
6527
6528 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6529 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6530 (curproxy->cap & cfg_opts[optnum].cap) &&
6531 (curproxy->options & cfg_opts[optnum].val)) {
6532 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6533 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6534 err_code |= ERR_WARN;
6535 curproxy->options &= ~cfg_opts[optnum].val;
6536 }
6537 }
6538
6539 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6540 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6541 (curproxy->cap & cfg_opts2[optnum].cap) &&
6542 (curproxy->options2 & cfg_opts2[optnum].val)) {
6543 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6544 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6545 err_code |= ERR_WARN;
6546 curproxy->options2 &= ~cfg_opts2[optnum].val;
6547 }
6548 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006549
Willy Tarreauefa5f512010-03-30 20:13:29 +02006550#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006551 if (curproxy->bind_hdr_occ) {
6552 curproxy->bind_hdr_occ = 0;
6553 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6554 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6555 err_code |= ERR_WARN;
6556 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006557#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006558 }
6559
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006561 * ensure that we're not cross-dressing a TCP server into HTTP.
6562 */
6563 newsrv = curproxy->srv;
6564 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006565 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006566 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6567 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006568 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006569 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006570
Willy Tarreau0cec3312011-10-31 13:49:26 +01006571 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6572 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6573 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6574 err_code |= ERR_WARN;
6575 }
6576
Willy Tarreauefa5f512010-03-30 20:13:29 +02006577#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006578 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6579 newsrv->bind_hdr_occ = 0;
6580 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6581 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6582 err_code |= ERR_WARN;
6583 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006584#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006585 newsrv = newsrv->next;
6586 }
6587
Willy Tarreauc1a21672009-08-16 22:37:44 +02006588 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006589 if (!curproxy->accept)
6590 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006591
Willy Tarreauc1a21672009-08-16 22:37:44 +02006592 if (curproxy->tcp_req.inspect_delay ||
6593 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006594 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006595
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006596 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006597 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006598 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006599 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006600
6601 /* both TCP and HTTP must check switching rules */
6602 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6603 }
6604
6605 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006606 if (curproxy->tcp_req.inspect_delay ||
6607 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6608 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6609
Emeric Brun97679e72010-09-23 17:56:44 +02006610 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6611 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6612
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006613 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006614 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006615 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006616 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006617
6618 /* If the backend does requires RDP cookie persistence, we have to
6619 * enable the corresponding analyser.
6620 */
6621 if (curproxy->options2 & PR_O2_RDPC_PRST)
6622 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6623 }
6624
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006625 /* Configure SSL for each bind line.
6626 * Note: if configuration fails at some point, the ->ctx member
6627 * remains NULL so that listeners can later detach.
6628 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006629 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6630 if (!bind_conf->is_ssl)
6631 continue;
6632#ifdef USE_OPENSSL
6633 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006634 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006635 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006636 cfgerr++;
6637 continue;
6638 }
6639
Emeric Brun4b3091e2012-09-24 15:48:52 +02006640 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006641 Alert("Unable to allocate SSL session cache.\n");
6642 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006643 continue;
6644 }
6645
Emeric Brunfc0421f2012-09-07 17:30:07 +02006646 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006647 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006648#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006649 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006650
Willy Tarreaue6b98942007-10-29 01:09:36 +01006651 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006652 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006653 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006654 if (!listener->luid) {
6655 /* listener ID not set, use automatic numbering with first
6656 * spare entry starting with next_luid.
6657 */
6658 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6659 listener->conf.id.key = listener->luid = next_id;
6660 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006661 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006662 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006663
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006664 /* enable separate counters */
6665 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6666 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006667 if (!listener->name)
6668 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006669 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006670
Willy Tarreaue6b98942007-10-29 01:09:36 +01006671 if (curproxy->options & PR_O_TCP_NOLING)
6672 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006673 if (!listener->maxconn)
6674 listener->maxconn = curproxy->maxconn;
6675 if (!listener->backlog)
6676 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006677 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006678 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006679 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006680 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006681
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006682 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6683 listener->options |= LI_O_TCP_RULES;
6684
Willy Tarreaude3041d2010-05-31 10:56:17 +02006685 if (curproxy->mon_mask.s_addr)
6686 listener->options |= LI_O_CHK_MONNET;
6687
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006688 /* smart accept mode is automatic in HTTP mode */
6689 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006690 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006691 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6692 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006693 }
6694
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006695 /* Release unused SSL configs */
6696 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6697 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006698 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006699#ifdef USE_OPENSSL
6700 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006701 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006702 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006703 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006704 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006705#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006706 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006707
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006708 /* Check multi-process mode compatibility for the current proxy */
6709 if (global.nbproc > 1) {
6710 int nbproc = 0;
6711 if (curproxy->bind_proc) {
6712 int proc;
6713 for (proc = 0; proc < global.nbproc; proc++) {
6714 if (curproxy->bind_proc & (1 << proc)) {
6715 nbproc++;
6716 }
6717 }
6718 } else {
6719 nbproc = global.nbproc;
6720 }
6721 if (curproxy->table.peers.name) {
6722 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6723 curproxy->id);
6724 cfgerr++;
6725 }
6726 if (nbproc > 1) {
6727 if (curproxy->uri_auth) {
6728 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6729 curproxy->id);
6730 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6731 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6732 curproxy->id);
6733 }
6734 }
6735 if (curproxy->appsession_name) {
6736 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6737 curproxy->id);
6738 }
6739 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6740 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6741 curproxy->id);
6742 }
6743 }
6744 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006745
6746 /* create the task associated with the proxy */
6747 curproxy->task = task_new();
6748 if (curproxy->task) {
6749 curproxy->task->context = curproxy;
6750 curproxy->task->process = manage_proxy;
6751 /* no need to queue, it will be done automatically if some
6752 * listener gets limited.
6753 */
6754 curproxy->task->expire = TICK_ETERNITY;
6755 } else {
6756 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6757 curproxy->id);
6758 cfgerr++;
6759 }
6760
Willy Tarreaubaaee002006-06-26 02:48:02 +02006761 curproxy = curproxy->next;
6762 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006763
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006764 /* Check multi-process mode compatibility */
6765 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006766 if (global.stats_fe && !global.stats_fe->bind_proc) {
6767 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 +01006768 }
6769 }
6770
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6772 struct auth_users *curuser;
6773 int g;
6774
6775 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6776 unsigned int group_mask = 0;
6777 char *group = NULL;
6778
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006779 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006780 continue;
6781
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006782 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006783
6784 for (g = 0; g < curuserlist->grpcnt; g++)
6785 if (!strcmp(curuserlist->groups[g], group))
6786 break;
6787
6788 if (g == curuserlist->grpcnt) {
6789 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6790 curuserlist->name, group, curuser->user);
6791 err_code |= ERR_ALERT | ERR_FATAL;
6792 goto out;
6793 }
6794
6795 group_mask |= (1 << g);
6796 }
6797
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006798 free(curuser->u.groups);
6799 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 }
6801
6802 for (g = 0; g < curuserlist->grpcnt; g++) {
6803 char *user = NULL;
6804
6805 if (!curuserlist->groupusers[g])
6806 continue;
6807
6808 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6809 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6810 if (!strcmp(curuser->user, user))
6811 break;
6812
6813 if (!curuser) {
6814 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6815 curuserlist->name, user, curuserlist->groups[g]);
6816 err_code |= ERR_ALERT | ERR_FATAL;
6817 goto out;
6818 }
6819
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006820 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006821 }
6822
6823 free(curuserlist->groupusers[g]);
6824 }
6825
6826 free(curuserlist->groupusers);
6827
6828#ifdef DEBUG_AUTH
6829 for (g = 0; g < curuserlist->grpcnt; g++) {
6830 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6831
6832 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006833 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006834 fprintf(stderr, " %s", curuser->user);
6835 }
6836
6837 fprintf(stderr, "\n");
6838 }
6839#endif
6840
Willy Tarreaufbb78422011-06-05 15:38:35 +02006841 }
6842
6843 /* automatically compute fullconn if not set. We must not do it in the
6844 * loop above because cross-references are not yet fully resolved.
6845 */
6846 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6847 /* If <fullconn> is not set, let's set it to 10% of the sum of
6848 * the possible incoming frontend's maxconns.
6849 */
6850 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6851 struct proxy *fe;
6852 int total = 0;
6853
6854 /* sum up the number of maxconns of frontends which
6855 * reference this backend at least once or which are
6856 * the same one ('listen').
6857 */
6858 for (fe = proxy; fe; fe = fe->next) {
6859 struct switching_rule *rule;
6860 struct hdr_exp *exp;
6861 int found = 0;
6862
6863 if (!(fe->cap & PR_CAP_FE))
6864 continue;
6865
6866 if (fe == curproxy) /* we're on a "listen" instance */
6867 found = 1;
6868
6869 if (fe->defbe.be == curproxy) /* "default_backend" */
6870 found = 1;
6871
6872 /* check if a "use_backend" rule matches */
6873 if (!found) {
6874 list_for_each_entry(rule, &fe->switching_rules, list) {
6875 if (rule->be.backend == curproxy) {
6876 found = 1;
6877 break;
6878 }
6879 }
6880 }
6881
6882 /* check if a "reqsetbe" rule matches */
6883 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6884 if (exp->action == ACT_SETBE &&
6885 (struct proxy *)exp->replace == curproxy) {
6886 found = 1;
6887 break;
6888 }
6889 }
6890
6891 /* now we've checked all possible ways to reference a backend
6892 * from a frontend.
6893 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006894 if (!found)
6895 continue;
6896 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006897 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006898 /* we have the sum of the maxconns in <total>. We only
6899 * keep 10% of that sum to set the default fullconn, with
6900 * a hard minimum of 1 (to avoid a divide by zero).
6901 */
6902 curproxy->fullconn = (total + 9) / 10;
6903 if (!curproxy->fullconn)
6904 curproxy->fullconn = 1;
6905 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006906 }
6907
Willy Tarreau056f5682010-06-06 15:51:11 +02006908 /* initialize stick-tables on backend capable proxies. This must not
6909 * be done earlier because the data size may be discovered while parsing
6910 * other proxies.
6911 */
6912 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006913 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006914
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006915 /*
6916 * Recount currently required checks.
6917 */
6918
6919 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6920 int optnum;
6921
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006922 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6923 if (curproxy->options & cfg_opts[optnum].val)
6924 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006925
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006926 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6927 if (curproxy->options2 & cfg_opts2[optnum].val)
6928 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006929 }
6930
Willy Tarreau122541c2011-09-07 21:24:49 +02006931 if (peers) {
6932 struct peers *curpeers = peers, **last;
6933 struct peer *p, *pb;
6934
6935 /* Remove all peers sections which don't have a valid listener.
6936 * This can happen when a peers section is never referenced and
6937 * does not contain a local peer.
6938 */
6939 last = &peers;
6940 while (*last) {
6941 curpeers = *last;
6942 if (curpeers->peers_fe) {
6943 last = &curpeers->next;
6944 continue;
6945 }
6946
6947 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6948 curpeers->id, localpeer);
6949
6950 p = curpeers->remote;
6951 while (p) {
6952 pb = p->next;
6953 free(p->id);
6954 free(p);
6955 p = pb;
6956 }
6957
6958 /* Destroy and unlink this curpeers section.
6959 * Note: curpeers is backed up into *last.
6960 */
6961 free(curpeers->id);
6962 curpeers = curpeers->next;
6963 free(*last);
6964 *last = curpeers;
6965 }
6966 }
6967
Willy Tarreauac1932d2011-10-24 19:14:41 +02006968 if (!global.tune.max_http_hdr)
6969 global.tune.max_http_hdr = MAX_HTTP_HDR;
6970
Willy Tarreau34eb6712011-10-24 18:15:04 +02006971 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006972 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006973 MEM_F_SHARED);
6974
Willy Tarreaubb925012009-07-23 13:36:36 +02006975 if (cfgerr > 0)
6976 err_code |= ERR_ALERT | ERR_FATAL;
6977 out:
6978 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006979}
6980
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006981/*
6982 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6983 * parsing sessions.
6984 */
6985void cfg_register_keywords(struct cfg_kw_list *kwl)
6986{
6987 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6988}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006989
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006990/*
6991 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6992 */
6993void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6994{
6995 LIST_DEL(&kwl->list);
6996 LIST_INIT(&kwl->list);
6997}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006998
6999/*
7000 * Local variables:
7001 * c-indent-level: 8
7002 * c-basic-offset: 8
7003 * End:
7004 */