blob: 282c128e6c7d0cbf810684b0f461de6fdc3f47bd [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 Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.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 Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020065#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010067#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
Emeric Brunfc0421f2012-09-07 17:30:07 +020069#ifdef USE_OPENSSL
70#include <types/ssl_sock.h>
71#include <proto/ssl_sock.h>
72#include <proto/shctx.h>
73#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020074
Willy Tarreauf3c69202006-07-09 16:42:34 +020075/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
76 * ssl-hello-chk option to ensure that the remote server speaks SSL.
77 *
78 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
79 */
80const char sslv3_client_hello_pkt[] = {
81 "\x16" /* ContentType : 0x16 = Hanshake */
82 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
83 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
84 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
85 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
86 "\x03\x00" /* Hello Version : 0x0300 = v3 */
87 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
88 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
89 "\x00" /* Session ID length : empty (no session ID) */
90 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
91 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
92 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
93 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
94 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
95 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
96 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
97 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
98 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
99 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
100 "\x00\x38" "\x00\x39" "\x00\x3A"
101 "\x01" /* Compression Length : 0x01 = 1 byte for types */
102 "\x00" /* Compression Type : 0x00 = NULL compression */
103};
104
Willy Tarreau3842f002009-06-14 11:39:52 +0200105/* various keyword modifiers */
106enum kw_mod {
107 KWM_STD = 0, /* normal */
108 KWM_NO, /* "no" prefixed before the keyword */
109 KWM_DEF, /* "default" prefixed before the keyword */
110};
111
Willy Tarreau13943ab2006-12-31 00:24:10 +0100112/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100113struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114 const char *name;
115 unsigned int val;
116 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100117 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100118 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100119};
120
121/* proxy->options */
122static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100123{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100124 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
125 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
126 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
128 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
129 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
130 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
134 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
136 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
137 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
138 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
139 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100140#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100142#else
143 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100144#endif
145
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147};
148
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100149/* proxy->options2 */
150static const struct cfg_opt cfg_opts2[] =
151{
152#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
155 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100156#else
157 { "splice-request", 0, 0, 0, 0 },
158 { "splice-response", 0, 0, 0, 0 },
159 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100160#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
162 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
163 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
164 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
165 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
166 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
168 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
169 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400170 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200172 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200173 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174 { NULL, 0, 0, 0 }
175};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176
Willy Tarreau6daf3432008-01-22 16:44:08 +0100177static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
179int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100180int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200182/* List head of all known configuration keywords */
183static struct cfg_kw_list cfg_keywords = {
184 .list = LIST_HEAD_INIT(cfg_keywords.list)
185};
186
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187/*
188 * converts <str> to a list of listeners which are dynamically allocated.
189 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
190 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
191 * - <port> is a numerical port from 1 to 65535 ;
192 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
193 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200194 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100196static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197{
198 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100199 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 int port, end;
201
202 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200203
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 while (next && *next) {
205 struct sockaddr_storage ss;
206
207 str = next;
208 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100209 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 *next++ = 0;
211 }
212
Emeric Bruned760922010-10-22 17:59:25 +0200213 if (*str == '/') {
214 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
215 /* so compute max path */
216 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
217 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 +0200218
Emeric Bruned760922010-10-22 17:59:25 +0200219 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100220 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
221 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200222 goto fail;
223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200226 ss.ss_family = AF_UNIX;
227 if (global.unix_bind.prefix) {
228 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
229 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
Emeric Bruned760922010-10-22 17:59:25 +0200231 else {
232 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
233 }
234 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 }
236 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100239 ss2 = str2sa_range(str, &port, &end);
240 if (!ss2) {
241 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
242 file, line, str);
243 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 if (!port) {
247 Alert("parsing [%s:%d] : missing port number: '%s'\n",
248 file, line, str);
249 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 Tarreau2dff0c22011-03-04 15:43:13 +0100256 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
257 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100262 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
263 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
267
268 for (; port <= end; port++) {
269 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200270 l->next = curproxy->listen;
271 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272
273 l->fd = -1;
274 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200275 l->data = &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 {
287 l->perm.ux.gid = l->perm.ux.uid = -1;
288 l->perm.ux.mode = 0;
289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
472 else if (!strcmp(args[0], "daemon")) {
473 global.mode |= MODE_DAEMON;
474 }
475 else if (!strcmp(args[0], "debug")) {
476 global.mode |= MODE_DEBUG;
477 }
478 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100479 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200481 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100482 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200483 }
484 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100485 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100488 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100490 else if (!strcmp(args[0], "nosplice")) {
491 global.tune.options &= ~GTUNE_USE_SPLICE;
492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200493 else if (!strcmp(args[0], "quiet")) {
494 global.mode |= MODE_QUIET;
495 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 else if (!strcmp(args[0], "tune.maxpollevents")) {
497 if (global.tune.maxpollevents != 0) {
498 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT;
500 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200501 }
502 if (*(args[1]) == 0) {
503 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200506 }
507 global.tune.maxpollevents = atol(args[1]);
508 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 else if (!strcmp(args[0], "tune.maxaccept")) {
510 if (global.tune.maxaccept != 0) {
511 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200512 err_code |= ERR_ALERT;
513 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100514 }
515 if (*(args[1]) == 0) {
516 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200517 err_code |= ERR_ALERT | ERR_FATAL;
518 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100519 }
520 global.tune.maxaccept = atol(args[1]);
521 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200522 else if (!strcmp(args[0], "tune.chksize")) {
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527 }
528 global.tune.chksize = atol(args[1]);
529 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200530#ifdef USE_OPENSSL
531 else if (!strcmp(args[0], "tune.sslcachesize")) {
532 if (*(args[1]) == 0) {
533 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
534 err_code |= ERR_ALERT | ERR_FATAL;
535 goto out;
536 }
537 global.tune.sslcachesize = atol(args[1]);
538 }
539#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200540 else if (!strcmp(args[0], "tune.bufsize")) {
541 if (*(args[1]) == 0) {
542 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT | ERR_FATAL;
544 goto out;
545 }
546 global.tune.bufsize = atol(args[1]);
547 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
548 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200549 trashlen = global.tune.bufsize;
550 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200551 }
552 else if (!strcmp(args[0], "tune.maxrewrite")) {
553 if (*(args[1]) == 0) {
554 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT | ERR_FATAL;
556 goto out;
557 }
558 global.tune.maxrewrite = atol(args[1]);
559 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
560 global.tune.maxrewrite = global.tune.bufsize / 2;
561 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100562 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
563 if (global.tune.client_rcvbuf != 0) {
564 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT;
566 goto out;
567 }
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.client_rcvbuf = atol(args[1]);
574 }
575 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
576 if (global.tune.server_rcvbuf != 0) {
577 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT;
579 goto out;
580 }
581 if (*(args[1]) == 0) {
582 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585 }
586 global.tune.server_rcvbuf = atol(args[1]);
587 }
588 else if (!strcmp(args[0], "tune.sndbuf.client")) {
589 if (global.tune.client_sndbuf != 0) {
590 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
591 err_code |= ERR_ALERT;
592 goto out;
593 }
594 if (*(args[1]) == 0) {
595 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT | ERR_FATAL;
597 goto out;
598 }
599 global.tune.client_sndbuf = atol(args[1]);
600 }
601 else if (!strcmp(args[0], "tune.sndbuf.server")) {
602 if (global.tune.server_sndbuf != 0) {
603 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT;
605 goto out;
606 }
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.server_sndbuf = atol(args[1]);
613 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200614 else if (!strcmp(args[0], "tune.pipesize")) {
615 if (*(args[1]) == 0) {
616 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT | ERR_FATAL;
618 goto out;
619 }
620 global.tune.pipesize = atol(args[1]);
621 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200622 else if (!strcmp(args[0], "tune.http.maxhdr")) {
623 if (*(args[1]) == 0) {
624 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT | ERR_FATAL;
626 goto out;
627 }
628 global.tune.max_http_hdr = atol(args[1]);
629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 else if (!strcmp(args[0], "uid")) {
631 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT;
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 }
636 if (*(args[1]) == 0) {
637 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT | ERR_FATAL;
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 }
641 global.uid = atol(args[1]);
642 }
643 else if (!strcmp(args[0], "gid")) {
644 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200645 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT;
647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 }
649 if (*(args[1]) == 0) {
650 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200651 err_code |= ERR_ALERT | ERR_FATAL;
652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 }
654 global.gid = atol(args[1]);
655 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200656 /* user/group name handling */
657 else if (!strcmp(args[0], "user")) {
658 struct passwd *ha_user;
659 if (global.uid != 0) {
660 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200661 err_code |= ERR_ALERT;
662 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200663 }
664 errno = 0;
665 ha_user = getpwnam(args[1]);
666 if (ha_user != NULL) {
667 global.uid = (int)ha_user->pw_uid;
668 }
669 else {
670 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 +0200671 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200672 }
673 }
674 else if (!strcmp(args[0], "group")) {
675 struct group *ha_group;
676 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200677 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT;
679 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200680 }
681 errno = 0;
682 ha_group = getgrnam(args[1]);
683 if (ha_group != NULL) {
684 global.gid = (int)ha_group->gr_gid;
685 }
686 else {
687 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 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200689 }
690 }
691 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 else if (!strcmp(args[0], "nbproc")) {
693 if (global.nbproc != 0) {
694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200695 err_code |= ERR_ALERT;
696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 }
698 if (*(args[1]) == 0) {
699 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT | ERR_FATAL;
701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 }
703 global.nbproc = atol(args[1]);
704 }
705 else if (!strcmp(args[0], "maxconn")) {
706 if (global.maxconn != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT;
709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715 }
716 global.maxconn = atol(args[1]);
717#ifdef SYSTEM_MAXCONN
718 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
719 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);
720 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200721 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200722 }
723#endif /* SYSTEM_MAXCONN */
724 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200725 else if (!strcmp(args[0], "maxsslconn")) {
726#ifdef USE_OPENSSL
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 global.maxsslconn = atol(args[1]);
733#else
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739#endif
740 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200741 else if (!strcmp(args[0], "maxconnrate")) {
742 if (global.cps_lim != 0) {
743 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
744 err_code |= ERR_ALERT;
745 goto out;
746 }
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
751 }
752 global.cps_lim = atol(args[1]);
753 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100754 else if (!strcmp(args[0], "maxpipes")) {
755 if (global.maxpipes != 0) {
756 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT;
758 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100759 }
760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100764 }
765 global.maxpipes = atol(args[1]);
766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 else if (!strcmp(args[0], "ulimit-n")) {
768 if (global.rlimit_nofile != 0) {
769 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200770 err_code |= ERR_ALERT;
771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 }
773 if (*(args[1]) == 0) {
774 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200777 }
778 global.rlimit_nofile = atol(args[1]);
779 }
780 else if (!strcmp(args[0], "chroot")) {
781 if (global.chroot != NULL) {
782 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200783 err_code |= ERR_ALERT;
784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
786 if (*(args[1]) == 0) {
787 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT | ERR_FATAL;
789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200790 }
791 global.chroot = strdup(args[1]);
792 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200793 else if (!strcmp(args[0], "description")) {
794 int i, len=0;
795 char *d;
796
797 if (!*args[1]) {
798 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
799 file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 for(i=1; *args[i]; i++)
805 len += strlen(args[i])+1;
806
807 if (global.desc)
808 free(global.desc);
809
810 global.desc = d = (char *)calloc(1, len);
811
812 d += sprintf(d, "%s", args[1]);
813 for(i=2; *args[i]; i++)
814 d += sprintf(d, " %s", args[i]);
815 }
816 else if (!strcmp(args[0], "node")) {
817 int i;
818 char c;
819
820 for (i=0; args[1][i]; i++) {
821 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100822 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
823 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200824 break;
825 }
826
827 if (!i || args[1][i]) {
828 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
829 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
830 file, linenum, args[0]);
831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
833 }
834
835 if (global.node)
836 free(global.node);
837
838 global.node = strdup(args[1]);
839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200840 else if (!strcmp(args[0], "pidfile")) {
841 if (global.pidfile != NULL) {
842 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 }
846 if (*(args[1]) == 0) {
847 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200848 err_code |= ERR_ALERT | ERR_FATAL;
849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200850 }
851 global.pidfile = strdup(args[1]);
852 }
Emeric Bruned760922010-10-22 17:59:25 +0200853 else if (!strcmp(args[0], "unix-bind")) {
854 int cur_arg = 1;
855 while (*(args[cur_arg])) {
856 if (!strcmp(args[cur_arg], "prefix")) {
857 if (global.unix_bind.prefix != NULL) {
858 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
859 err_code |= ERR_ALERT;
860 cur_arg += 2;
861 continue;
862 }
863
864 if (*(args[cur_arg+1]) == 0) {
865 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868 }
869 global.unix_bind.prefix = strdup(args[cur_arg+1]);
870 cur_arg += 2;
871 continue;
872 }
873
874 if (!strcmp(args[cur_arg], "mode")) {
875
876 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
877 cur_arg += 2;
878 continue;
879 }
880
881 if (!strcmp(args[cur_arg], "uid")) {
882
883 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
884 cur_arg += 2;
885 continue;
886 }
887
888 if (!strcmp(args[cur_arg], "gid")) {
889
890 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
891 cur_arg += 2;
892 continue;
893 }
894
895 if (!strcmp(args[cur_arg], "user")) {
896 struct passwd *user;
897
898 user = getpwnam(args[cur_arg + 1]);
899 if (!user) {
900 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
901 file, linenum, args[0], args[cur_arg + 1 ]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905
906 global.unix_bind.ux.uid = user->pw_uid;
907 cur_arg += 2;
908 continue;
909 }
910
911 if (!strcmp(args[cur_arg], "group")) {
912 struct group *group;
913
914 group = getgrnam(args[cur_arg + 1]);
915 if (!group) {
916 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
917 file, linenum, args[0], args[cur_arg + 1 ]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921
922 global.unix_bind.ux.gid = group->gr_gid;
923 cur_arg += 2;
924 continue;
925 }
926
Willy Tarreaub48f9582011-09-05 01:17:06 +0200927 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200928 file, linenum, args[0]);
929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
931 }
932 }
William Lallemand0f99e342011-10-12 17:50:54 +0200933 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
934 /* delete previous herited or defined syslog servers */
935 struct logsrv *back;
936 struct logsrv *tmp;
937
938 if (*(args[1]) != 0) {
939 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943
944 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
945 LIST_DEL(&tmp->list);
946 free(tmp);
947 }
948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200950 struct logsrv *logsrv;
951
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 if (*(args[1]) == 0 || *(args[2]) == 0) {
953 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956 }
William Lallemand0f99e342011-10-12 17:50:54 +0200957
958 logsrv = calloc(1, sizeof(struct logsrv));
959
960 logsrv->facility = get_log_facility(args[2]);
961 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200963 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200964 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200969 logsrv->level = get_log_level(args[3]);
970 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200972 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200973 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 }
975 }
976
William Lallemand0f99e342011-10-12 17:50:54 +0200977 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200978 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200979 logsrv->minlvl = get_log_level(args[4]);
980 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200981 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200983 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200984 }
985 }
986
Robert Tsai81ae1952007-12-05 10:47:29 +0100987 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100988 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100989 if (!sk) {
990 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100991 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100992 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200993 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100994 goto out;
995 }
William Lallemand0f99e342011-10-12 17:50:54 +0200996 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100997 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100998 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100999 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001000 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001002 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001003 goto out;
1004 }
William Lallemand0f99e342011-10-12 17:50:54 +02001005 logsrv->addr = *sk;
1006 if (!get_host_port(&logsrv->addr))
1007 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001009
William Lallemand0f99e342011-10-12 17:50:54 +02001010 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001011 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001012 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1013 char *name;
1014 int len;
1015
1016 if (global.log_send_hostname != NULL) {
1017 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT;
1019 goto out;
1020 }
1021
1022 if (*(args[1]))
1023 name = args[1];
1024 else
1025 name = hostname;
1026
1027 len = strlen(name);
1028
1029 /* We'll add a space after the name to respect the log format */
1030 free(global.log_send_hostname);
1031 global.log_send_hostname = malloc(len + 2);
1032 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1033 }
Kevinm48936af2010-12-22 16:08:21 +00001034 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1035 if (*(args[1]) == 0) {
1036 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 free(global.log_tag);
1041 global.log_tag = strdup(args[1]);
1042 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001043 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1044 if (global.spread_checks != 0) {
1045 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT;
1047 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001048 }
1049 if (*(args[1]) == 0) {
1050 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
1052 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001053 }
1054 global.spread_checks = atol(args[1]);
1055 if (global.spread_checks < 0 || global.spread_checks > 50) {
1056 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
1060 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001061 struct cfg_kw_list *kwl;
1062 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001063 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001064
1065 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1066 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1067 if (kwl->kw[index].section != CFG_GLOBAL)
1068 continue;
1069 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1070 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001071 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001072 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001073 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001074 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001075 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001076 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001077 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001078 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001079 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001080 err_code |= ERR_WARN;
1081 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001082 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001083 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001084 }
1085 }
1086 }
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001089 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001091
Willy Tarreau058e9072009-07-20 09:30:05 +02001092 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001093 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001094 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001095}
1096
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001097void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001099 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001100 defproxy.mode = PR_MODE_TCP;
1101 defproxy.state = PR_STNEW;
1102 defproxy.maxconn = cfg_maxpconn;
1103 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001104
1105 defproxy.defsrv.inter = DEF_CHKINTR;
1106 defproxy.defsrv.fastinter = 0;
1107 defproxy.defsrv.downinter = 0;
1108 defproxy.defsrv.rise = DEF_RISETIME;
1109 defproxy.defsrv.fall = DEF_FALLTIME;
1110 defproxy.defsrv.check_port = 0;
1111 defproxy.defsrv.maxqueue = 0;
1112 defproxy.defsrv.minconn = 0;
1113 defproxy.defsrv.maxconn = 0;
1114 defproxy.defsrv.slowstart = 0;
1115 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1116 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1117 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118}
1119
Willy Tarreauade5ec42010-01-28 19:33:49 +01001120
1121static int create_cond_regex_rule(const char *file, int line,
1122 struct proxy *px, int dir, int action, int flags,
1123 const char *cmd, const char *reg, const char *repl,
1124 const char **cond_start)
1125{
1126 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001127 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001128 const char *err;
1129 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001131
1132 if (px == &defproxy) {
1133 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto err;
1136 }
1137
1138 if (*reg == 0) {
1139 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto err;
1142 }
1143
1144 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1145 err_code |= ERR_WARN;
1146
Willy Tarreau5321c422010-01-28 20:35:13 +01001147 if (cond_start &&
1148 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001149 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1150 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1151 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto err;
1154 }
1155 }
1156 else if (cond_start && **cond_start) {
1157 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1158 file, line, cmd, *cond_start);
1159 err_code |= ERR_ALERT | ERR_FATAL;
1160 goto err;
1161 }
1162
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001163 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001164 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001165 else
1166 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001167
Willy Tarreauade5ec42010-01-28 19:33:49 +01001168 preg = calloc(1, sizeof(regex_t));
1169 if (!preg) {
1170 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1171 err_code = ERR_ALERT | ERR_FATAL;
1172 goto err;
1173 }
1174
1175 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1176 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1177 err_code = ERR_ALERT | ERR_FATAL;
1178 goto err;
1179 }
1180
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001181 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001182 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001183 if (repl && err) {
1184 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1185 file, line, cmd, *err);
1186 err_code |= ERR_ALERT | ERR_FATAL;
1187 goto err;
1188 }
1189
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001190 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001191 err_code |= ERR_WARN;
1192
Willy Tarreauf4068b62012-05-08 17:37:49 +02001193 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001194 return err_code;
1195 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001196 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001197 free(preg);
1198 return err_code;
1199}
1200
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001202 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001203 * Returns the error code, 0 if OK, or any combination of :
1204 * - ERR_ABORT: must abort ASAP
1205 * - ERR_FATAL: we can continue parsing but not start the service
1206 * - ERR_WARN: a warning has been emitted
1207 * - ERR_ALERT: an alert has been emitted
1208 * Only the two first ones can stop processing, the two others are just
1209 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001210 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001211int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1212{
1213 static struct peers *curpeers = NULL;
1214 struct peer *newpeer = NULL;
1215 const char *err;
1216 int err_code = 0;
1217
1218 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1219
1220 err = invalid_char(args[1]);
1221 if (err) {
1222 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1223 file, linenum, *err, args[0], args[1]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 }
1226
1227 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1228 /*
1229 * If there are two proxies with the same name only following
1230 * combinations are allowed:
1231 */
1232 if (strcmp(curpeers->id, args[1]) == 0) {
1233 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1234 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1235 err_code |= ERR_WARN;
1236 }
1237 }
1238
1239 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1240 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1241 err_code |= ERR_ALERT | ERR_ABORT;
1242 goto out;
1243 }
1244
1245 curpeers->next = peers;
1246 peers = curpeers;
1247 curpeers->conf.file = file;
1248 curpeers->conf.line = linenum;
1249 curpeers->last_change = now.tv_sec;
1250 curpeers->id = strdup(args[1]);
1251 }
1252 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1253 char *rport, *raddr;
1254 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001255 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001256
1257 if (!*args[2]) {
1258 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1259 file, linenum, args[0]);
1260 err_code |= ERR_ALERT | ERR_FATAL;
1261 goto out;
1262 }
1263
1264 err = invalid_char(args[1]);
1265 if (err) {
1266 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1267 file, linenum, *err, args[1]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1274 err_code |= ERR_ALERT | ERR_ABORT;
1275 goto out;
1276 }
1277
1278 /* the peers are linked backwards first */
1279 curpeers->count++;
1280 newpeer->next = curpeers->remote;
1281 curpeers->remote = newpeer;
1282 newpeer->peers = curpeers;
1283 newpeer->conf.file = file;
1284 newpeer->conf.line = linenum;
1285
1286 newpeer->last_change = now.tv_sec;
1287 newpeer->id = strdup(args[1]);
1288
1289 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001290 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001291 if (rport) {
1292 *rport++ = 0;
1293 realport = atol(rport);
1294 }
1295 if (!realport) {
1296 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
1299 }
1300
Willy Tarreaufab5a432011-03-04 15:31:53 +01001301 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001302 free(raddr);
1303 if (!sk) {
1304 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1305 err_code |= ERR_ALERT | ERR_FATAL;
1306 goto out;
1307 }
1308 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001309 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001310 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001311 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001312
1313 if (!sk) {
1314 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1315 file, linenum, newpeer->addr.ss_family, args[2]);
1316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
1318 }
1319
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001320 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001321
1322 if (strcmp(newpeer->id, localpeer) == 0) {
1323 /* Current is local peer, it define a frontend */
1324 newpeer->local = 1;
1325
1326 if (!curpeers->peers_fe) {
1327 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1328 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1329 err_code |= ERR_ALERT | ERR_ABORT;
1330 goto out;
1331 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001332
Willy Tarreau237250c2011-07-29 01:49:03 +02001333 init_new_proxy(curpeers->peers_fe);
1334 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001335
1336 curpeers->peers_fe->last_change = now.tv_sec;
1337 curpeers->peers_fe->id = strdup(args[1]);
1338 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001339 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001340 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1341 curpeers->peers_fe->timeout.connect = 5000;
1342 curpeers->peers_fe->accept = peer_accept;
1343 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001344 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001345 err_code |= ERR_FATAL;
1346 goto out;
1347 }
1348 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1349 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1350 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1351 curpeers->peers_fe->listen->accept = session_accept;
1352 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1353 curpeers->peers_fe->listen->handler = process_session;
1354 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001355 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1356 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001357 }
1358 }
1359 } /* neither "peer" nor "peers" */
1360 else if (*args[0] != 0) {
1361 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
1365
1366out:
1367 return err_code;
1368}
1369
1370
Willy Tarreau3842f002009-06-14 11:39:52 +02001371int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372{
1373 static struct proxy *curproxy = NULL;
1374 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001375 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001376 int rc;
1377 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001378 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001379 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001380 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001381 char *errmsg = NULL;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001382 struct ssl_conf *ssl_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383
Willy Tarreau977b8e42006-12-29 14:19:17 +01001384 if (!strcmp(args[0], "listen"))
1385 rc = PR_CAP_LISTEN;
1386 else if (!strcmp(args[0], "frontend"))
1387 rc = PR_CAP_FE | PR_CAP_RS;
1388 else if (!strcmp(args[0], "backend"))
1389 rc = PR_CAP_BE | PR_CAP_RS;
1390 else if (!strcmp(args[0], "ruleset"))
1391 rc = PR_CAP_RS;
1392 else
1393 rc = PR_CAP_NONE;
1394
1395 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 if (!*args[1]) {
1397 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1398 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001400 err_code |= ERR_ALERT | ERR_ABORT;
1401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001403
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001404 err = invalid_char(args[1]);
1405 if (err) {
1406 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1407 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001409 }
1410
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001411 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1412 /*
1413 * If there are two proxies with the same name only following
1414 * combinations are allowed:
1415 *
1416 * listen backend frontend ruleset
1417 * listen - - - -
1418 * backend - - OK -
1419 * frontend - OK - -
1420 * ruleset - - - -
1421 */
1422
1423 if (!strcmp(curproxy->id, args[1]) &&
1424 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1425 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001426 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1427 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1428 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001429 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001430 }
1431 }
1432
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1434 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001435 err_code |= ERR_ALERT | ERR_ABORT;
1436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001438
Willy Tarreau97cb7802010-01-03 20:23:58 +01001439 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 curproxy->next = proxy;
1441 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001442 curproxy->conf.file = file;
1443 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001444 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447
1448 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001449 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001450 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001451 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001452 err_code |= ERR_FATAL;
1453 goto out;
1454 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001455 new = curproxy->listen;
1456 while (new != last) {
1457 new->conf.file = file;
1458 new->conf.line = linenum;
1459 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001460 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 }
1463
1464 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001465 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001466 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001467
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001470 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001471 curproxy->no_options = defproxy.no_options;
1472 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001473 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001474 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001475 curproxy->except_net = defproxy.except_net;
1476 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001477 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001478 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001480 if (defproxy.fwdfor_hdr_len) {
1481 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1482 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1483 }
1484
Willy Tarreaub86db342009-11-30 11:50:16 +01001485 if (defproxy.orgto_hdr_len) {
1486 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1487 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1488 }
1489
Mark Lamourinec2247f02012-01-04 13:02:01 -05001490 if (defproxy.server_id_hdr_len) {
1491 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1492 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1493 }
1494
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if (curproxy->cap & PR_CAP_FE) {
1496 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001497 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001498 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001499
1500 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001501 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1502 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503
1504 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 if (curproxy->cap & PR_CAP_BE) {
1508 curproxy->fullconn = defproxy.fullconn;
1509 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001511 if (defproxy.check_req) {
1512 curproxy->check_req = calloc(1, defproxy.check_len);
1513 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1514 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001517 if (defproxy.expect_str) {
1518 curproxy->expect_str = strdup(defproxy.expect_str);
1519 if (defproxy.expect_regex) {
1520 /* note: this regex is known to be valid */
1521 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1522 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1523 }
1524 }
1525
Willy Tarreau67402132012-05-31 20:40:20 +02001526 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001527 if (defproxy.cookie_name)
1528 curproxy->cookie_name = strdup(defproxy.cookie_name);
1529 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001530 if (defproxy.cookie_domain)
1531 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001532
Willy Tarreau31936852010-10-06 16:59:56 +02001533 if (defproxy.cookie_maxidle)
1534 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1535
1536 if (defproxy.cookie_maxlife)
1537 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1538
Emeric Brun647caf12009-06-30 17:57:00 +02001539 if (defproxy.rdp_cookie_name)
1540 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1541 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1542
Willy Tarreau01732802007-11-01 22:48:15 +01001543 if (defproxy.url_param_name)
1544 curproxy->url_param_name = strdup(defproxy.url_param_name);
1545 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001546
Benoitaffb4812009-03-25 13:02:10 +01001547 if (defproxy.hh_name)
1548 curproxy->hh_name = strdup(defproxy.hh_name);
1549 curproxy->hh_len = defproxy.hh_len;
1550 curproxy->hh_match_domain = defproxy.hh_match_domain;
1551
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001552 if (defproxy.iface_name)
1553 curproxy->iface_name = strdup(defproxy.iface_name);
1554 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001557 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558 if (defproxy.capture_name)
1559 curproxy->capture_name = strdup(defproxy.capture_name);
1560 curproxy->capture_namelen = defproxy.capture_namelen;
1561 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001562 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563
Willy Tarreau977b8e42006-12-29 14:19:17 +01001564 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001565 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001566 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001567 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001568 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001569 curproxy->uri_auth = defproxy.uri_auth;
1570 curproxy->mon_net = defproxy.mon_net;
1571 curproxy->mon_mask = defproxy.mon_mask;
1572 if (defproxy.monitor_uri)
1573 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1574 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001575 if (defproxy.defbe.name)
1576 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001577
1578 /* get either a pointer to the logformat string or a copy of it */
1579 curproxy->logformat_string = defproxy.logformat_string;
1580 if (curproxy->logformat_string &&
1581 curproxy->logformat_string != default_http_log_format &&
1582 curproxy->logformat_string != default_tcp_log_format &&
1583 curproxy->logformat_string != clf_http_log_format)
1584 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001585 }
1586
1587 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001588 curproxy->timeout.connect = defproxy.timeout.connect;
1589 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001590 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001591 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001592 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001593 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001594 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001595 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001596 curproxy->source_addr = defproxy.source_addr;
1597 }
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001600
1601 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001602 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001603 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001604 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001605 LIST_INIT(&node->list);
1606 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1607 }
1608
Willy Tarreau196729e2012-05-31 19:30:26 +02001609 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1610 if (curproxy->uniqueid_format_string)
1611 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001612
1613 /* copy default header unique id */
1614 if (defproxy.header_unique_id)
1615 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1616
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001618 curproxy->conf.used_listener_id = EB_ROOT;
1619 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001620
Willy Tarreau93893792009-07-23 13:19:11 +02001621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1624 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001625 /* FIXME-20070101: we should do this too at the end of the
1626 * config parsing to free all default values.
1627 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001628 free(defproxy.check_req);
1629 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001630 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001631 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001632 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001633 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001634 free(defproxy.capture_name);
1635 free(defproxy.monitor_uri);
1636 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001637 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001638 free(defproxy.fwdfor_hdr_name);
1639 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001640 free(defproxy.orgto_hdr_name);
1641 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001642 free(defproxy.server_id_hdr_name);
1643 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001644 free(defproxy.expect_str);
1645 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001646
Willy Tarreau39b06652012-06-01 10:58:06 +02001647 if (defproxy.logformat_string != default_http_log_format &&
1648 defproxy.logformat_string != default_tcp_log_format &&
1649 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001650 free(defproxy.logformat_string);
1651
1652 free(defproxy.uniqueid_format_string);
1653
Willy Tarreaua534fea2008-08-03 12:19:50 +02001654 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001655 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001656
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 /* we cannot free uri_auth because it might already be used */
1658 init_default_instance();
1659 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001660 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001662 }
1663 else if (curproxy == NULL) {
1664 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 }
1668
Willy Tarreau977b8e42006-12-29 14:19:17 +01001669
1670 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001672 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001673 int cur_arg;
1674
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 if (curproxy == &defproxy) {
1676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001680 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682
Emeric Bruned760922010-10-22 17:59:25 +02001683 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001684 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001689
1690 last_listen = curproxy->listen;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001691 ssl_conf = NULL;
Willy Tarreau8a956912010-10-15 14:27:08 +02001692
1693 /* NOTE: the following line might create several listeners if there
1694 * are comma-separated IPs or port ranges. So all further processing
1695 * will have to be applied to all listeners created after last_listen.
1696 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001697 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
1700 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001701
Willy Tarreau90a570f2009-10-04 20:54:54 +02001702 new_listen = curproxy->listen;
1703 while (new_listen != last_listen) {
1704 new_listen->conf.file = file;
1705 new_listen->conf.line = linenum;
1706 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001707 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001708 }
1709
Emeric Bruned760922010-10-22 17:59:25 +02001710 /* Set default global rights and owner for unix bind */
1711 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1712 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1713 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001714 cur_arg = 2;
1715 while (*(args[cur_arg])) {
1716 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1717#ifdef SO_BINDTODEVICE
1718 struct listener *l;
1719
Emeric Bruned760922010-10-22 17:59:25 +02001720 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1721 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1722 file, linenum, args[0], args[cur_arg]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001727 if (!*args[cur_arg + 1]) {
1728 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001732 }
1733
1734 for (l = curproxy->listen; l != last_listen; l = l->next)
1735 l->interface = strdup(args[cur_arg + 1]);
1736
1737 global.last_checks |= LSTCHK_NETADM;
1738
1739 cur_arg += 2;
1740 continue;
1741#else
1742 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1743 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001746#endif
1747 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001748 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1749#ifdef TCP_MAXSEG
1750 struct listener *l;
1751 int mss;
1752
Emeric Bruned760922010-10-22 17:59:25 +02001753 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1754 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1755 file, linenum, args[0], args[cur_arg]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759
Willy Tarreaube1b9182009-06-14 18:48:19 +02001760 if (!*args[cur_arg + 1]) {
1761 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001765 }
1766
Willy Tarreau48a7e722010-12-24 15:26:39 +01001767 mss = atoi(args[cur_arg + 1]);
1768 if (!mss || abs(mss) > 65535) {
1769 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001773 }
1774
1775 for (l = curproxy->listen; l != last_listen; l = l->next)
1776 l->maxseg = mss;
1777
1778 cur_arg += 2;
1779 continue;
1780#else
1781 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1782 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001785#endif
1786 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001787
1788 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1789#ifdef TCP_DEFER_ACCEPT
1790 struct listener *l;
1791
1792 for (l = curproxy->listen; l != last_listen; l = l->next)
1793 l->options |= LI_O_DEF_ACCEPT;
1794
1795 cur_arg ++;
1796 continue;
1797#else
1798 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1799 file, linenum, args[0], args[cur_arg]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802#endif
1803 }
1804
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001805 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001806#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001807 struct listener *l;
1808
Emeric Bruned760922010-10-22 17:59:25 +02001809 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1810 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1811 file, linenum, args[0], args[cur_arg]);
1812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
1815
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001816 for (l = curproxy->listen; l != last_listen; l = l->next)
1817 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001818
1819 cur_arg ++;
1820 continue;
1821#else
1822 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1823 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001826#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001827 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001828
Willy Tarreau32368ce2012-09-06 11:10:55 +02001829 if (!strcmp(args[cur_arg], "maxconn")) {
1830 struct listener *l;
1831 int val;
1832
1833 if (!*args[cur_arg + 1]) {
1834 Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
1835 file, linenum, args[0]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839
1840 val = atol(args[cur_arg + 1]);
1841 if (val <= 0) {
1842 Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
1843 file, linenum, args[0], val);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 for (l = curproxy->listen; l != last_listen; l = l->next)
1849 l->maxconn = val;
1850
1851 cur_arg += 2;
1852 continue;
1853 }
1854
1855 if (!strcmp(args[cur_arg], "backlog")) {
1856 struct listener *l;
1857 int val;
1858
1859 if (!*args[cur_arg + 1]) {
1860 Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
1861 file, linenum, args[0]);
1862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
1865
1866 val = atol(args[cur_arg + 1]);
1867 if (val <= 0) {
1868 Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
1869 file, linenum, args[0], val);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872 }
1873
1874 for (l = curproxy->listen; l != last_listen; l = l->next)
1875 l->backlog = val;
1876
1877 cur_arg += 2;
1878 continue;
1879 }
1880
Willy Tarreau50acaaa2012-09-06 14:26:36 +02001881 if (!strcmp(args[cur_arg], "nice")) {
1882 struct listener *l;
1883 int val;
1884
1885 if (!*args[cur_arg + 1]) {
1886 Alert("parsing [%s:%d] : '%s' : missing nice value.\n",
1887 file, linenum, args[0]);
1888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
1890 }
1891
1892 val = atol(args[cur_arg + 1]);
1893 if (val < -1024 || val > 1024) {
1894 Alert("parsing [%s:%d] : '%s' : invalid nice value %d, allowed range is -1024..1024.\n",
1895 file, linenum, args[0], val);
1896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
1898 }
1899
1900 for (l = curproxy->listen; l != last_listen; l = l->next)
1901 l->nice = val;
1902
1903 cur_arg += 2;
1904 continue;
1905 }
1906
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001907 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl */
Emeric Brun6e159292012-05-18 16:32:13 +02001908#ifdef USE_OPENSSL
1909 struct listener *l;
1910
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001911 if (!ssl_conf)
1912 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
Emeric Brun6e159292012-05-18 16:32:13 +02001913
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001914 for (l = curproxy->listen; l != last_listen; l = l->next) {
1915 if (!l->ssl_conf) {
1916 l->ssl_conf = ssl_conf;
1917 ssl_conf->ref_cnt++;
1918 }
1919 }
Emeric Brun6e159292012-05-18 16:32:13 +02001920
Emeric Brunfc0421f2012-09-07 17:30:07 +02001921 cur_arg += 1;
1922 continue;
1923#else
1924 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1925 file, linenum, args[0], args[cur_arg]);
1926 err_code |= ERR_ALERT | ERR_FATAL;
1927 goto out;
1928#endif
1929 }
1930
1931 if (!strcmp(args[cur_arg], "crt")) { /* use ssl certificate */
1932#ifdef USE_OPENSSL
1933 if (!*args[cur_arg + 1]) {
1934 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1935 file, linenum, args[0]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940 if (!ssl_conf)
1941 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1942
1943 if (ssl_sock_load_cert(args[cur_arg + 1], ssl_conf, curproxy) > 0) {
1944 err_code |= ERR_ALERT | ERR_FATAL;
1945 goto out;
1946 }
1947
Emeric Brun6e159292012-05-18 16:32:13 +02001948 cur_arg += 2;
1949 continue;
1950#else
1951 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1952 file, linenum, args[0], args[cur_arg]);
1953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
1955#endif
1956 }
1957
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001958 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1959#ifdef USE_OPENSSL
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001960 if (!*args[cur_arg + 1]) {
1961 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1962 file, linenum, args[0]);
1963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
1965 }
1966
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001967 if (!ssl_conf)
1968 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1969 ssl_conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001970
1971 cur_arg += 2;
1972 continue;
1973#else
1974 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1975 file, linenum, args[0], args[cur_arg]);
1976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
1978#endif
1979 }
1980
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001981 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1982#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001983 if (!ssl_conf)
1984 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
1985 ssl_conf->nosslv3 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001986
1987 cur_arg += 1;
1988 continue;
1989#else
1990 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1991 file, linenum, args[0], args[cur_arg]);
1992 err_code |= ERR_ALERT | ERR_FATAL;
1993 goto out;
1994#endif
1995 }
1996
1997 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1998#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02001999 if (!ssl_conf)
2000 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
2001 ssl_conf->notlsv1 = 1;
Willy Tarreauc230b8b2012-09-03 23:55:16 +02002002
2003 cur_arg += 1;
2004 continue;
2005#else
2006 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2007 file, linenum, args[0], args[cur_arg]);
2008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
2010#endif
2011 }
2012
David BERARDe566ecb2012-09-04 15:15:13 +02002013 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
2014#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02002015 if (!ssl_conf)
2016 ssl_conf = ssl_conf_alloc(&curproxy->conf.ssl_bind, file, linenum, args[1]);
2017 ssl_conf->prefer_server_ciphers = 1;
David BERARDe566ecb2012-09-04 15:15:13 +02002018
2019 cur_arg += 1;
2020 continue;
2021#else
2022 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
2023 file, linenum, args[0], args[cur_arg]);
2024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
2026#endif
2027 }
2028
Willy Tarreau8a956912010-10-15 14:27:08 +02002029 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
2030 struct listener *l;
2031
2032 for (l = curproxy->listen; l != last_listen; l = l->next)
2033 l->options |= LI_O_ACC_PROXY;
2034
2035 cur_arg ++;
2036 continue;
2037 }
2038
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002039 if (!strcmp(args[cur_arg], "name")) {
2040 struct listener *l;
2041
2042 for (l = curproxy->listen; l != last_listen; l = l->next)
2043 l->name = strdup(args[cur_arg + 1]);
2044
2045 cur_arg += 2;
2046 continue;
2047 }
2048
2049 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002050 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002051 struct listener *l;
2052
2053 if (curproxy->listen->next != last_listen) {
2054 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
2055 file, linenum, args[cur_arg]);
2056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
2058 }
2059
2060 if (!*args[cur_arg + 1]) {
2061 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2062 file, linenum, args[cur_arg]);
2063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
2065 }
2066
2067 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002068 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002069
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002070 if (curproxy->listen->luid <= 0) {
2071 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002072 file, linenum);
2073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
2075 }
2076
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002077 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
2078 if (node) {
2079 l = container_of(node, struct listener, conf.id);
2080 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
2081 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
2082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
2084 }
2085 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
2086
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02002087 cur_arg += 2;
2088 continue;
2089 }
2090
Emeric Bruned760922010-10-22 17:59:25 +02002091 if (!strcmp(args[cur_arg], "mode")) {
2092
2093 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2094 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2095 file, linenum, args[0], args[cur_arg]);
2096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
2099
2100 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
2101
2102 cur_arg += 2;
2103 continue;
2104 }
2105
2106 if (!strcmp(args[cur_arg], "uid")) {
2107
2108 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2109 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2110 file, linenum, args[0], args[cur_arg]);
2111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
2113 }
2114
2115 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
2116 cur_arg += 2;
2117 continue;
2118 }
2119
2120 if (!strcmp(args[cur_arg], "gid")) {
2121
2122 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2123 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2124 file, linenum, args[0], args[cur_arg]);
2125 err_code |= ERR_ALERT | ERR_FATAL;
2126 goto out;
2127 }
2128
2129 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2130 cur_arg += 2;
2131 continue;
2132 }
2133
2134 if (!strcmp(args[cur_arg], "user")) {
2135 struct passwd *user;
2136
2137 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2138 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2139 file, linenum, args[0], args[cur_arg]);
2140 err_code |= ERR_ALERT | ERR_FATAL;
2141 goto out;
2142 }
2143 user = getpwnam(args[cur_arg + 1]);
2144 if (!user) {
2145 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2146 file, linenum, args[0], args[cur_arg + 1 ]);
2147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
2149 }
2150
2151 curproxy->listen->perm.ux.uid = user->pw_uid;
2152 cur_arg += 2;
2153 continue;
2154 }
2155
2156 if (!strcmp(args[cur_arg], "group")) {
2157 struct group *group;
2158
2159 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2160 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2161 file, linenum, args[0], args[cur_arg]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165 group = getgrnam(args[cur_arg + 1]);
2166 if (!group) {
2167 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2168 file, linenum, args[0], args[cur_arg + 1 ]);
2169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
2171 }
2172
2173 curproxy->listen->perm.ux.gid = group->gr_gid;
2174 cur_arg += 2;
2175 continue;
2176 }
2177
Willy Tarreaub48f9582011-09-05 01:17:06 +02002178 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002179 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002180 err_code |= ERR_ALERT | ERR_FATAL;
2181 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002182 }
Willy Tarreau93893792009-07-23 13:19:11 +02002183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 }
2185 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2186 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2187 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002192 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002194
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 /* flush useless bits */
2196 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002199 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202
Willy Tarreau1c47f852006-07-09 08:22:27 +02002203 if (!*args[1]) {
2204 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002208 }
2209
Willy Tarreaua534fea2008-08-03 12:19:50 +02002210 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002211 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002212 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002213 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002214 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2215
Willy Tarreau93893792009-07-23 13:19:11 +02002216 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2219 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2220 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2221 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2222 else {
2223 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002224 err_code |= ERR_ALERT | ERR_FATAL;
2225 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 }
2227 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002228 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002229 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002230
2231 if (curproxy == &defproxy) {
2232 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2233 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002234 err_code |= ERR_ALERT | ERR_FATAL;
2235 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002236 }
2237
2238 if (!*args[1]) {
2239 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2240 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 }
2244
2245 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002246 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002247
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002248 if (curproxy->uuid <= 0) {
2249 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002253 }
2254
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002255 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2256 if (node) {
2257 struct proxy *target = container_of(node, struct proxy, conf.id);
2258 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2259 file, linenum, proxy_type_str(curproxy), curproxy->id,
2260 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
2263 }
2264 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002265 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002266 else if (!strcmp(args[0], "description")) {
2267 int i, len=0;
2268 char *d;
2269
Cyril Bonté99ed3272010-01-24 23:29:44 +01002270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2272 file, linenum, args[0]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002277 if (!*args[1]) {
2278 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2279 file, linenum, args[0]);
2280 return -1;
2281 }
2282
2283 for(i=1; *args[i]; i++)
2284 len += strlen(args[i])+1;
2285
2286 d = (char *)calloc(1, len);
2287 curproxy->desc = d;
2288
2289 d += sprintf(d, "%s", args[1]);
2290 for(i=2; *args[i]; i++)
2291 d += sprintf(d, " %s", args[i]);
2292
2293 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002294 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2295 curproxy->state = PR_STSTOPPED;
2296 }
2297 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2298 curproxy->state = PR_STNEW;
2299 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002300 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2301 int cur_arg = 1;
2302 unsigned int set = 0;
2303
2304 while (*args[cur_arg]) {
2305 int u;
2306 if (strcmp(args[cur_arg], "all") == 0) {
2307 set = 0;
2308 break;
2309 }
2310 else if (strcmp(args[cur_arg], "odd") == 0) {
2311 set |= 0x55555555;
2312 }
2313 else if (strcmp(args[cur_arg], "even") == 0) {
2314 set |= 0xAAAAAAAA;
2315 }
2316 else {
2317 u = str2uic(args[cur_arg]);
2318 if (u < 1 || u > 32) {
2319 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_ALERT | ERR_FATAL;
2322 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002323 }
2324 if (u > global.nbproc) {
2325 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2326 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002327 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002328 }
2329 set |= 1 << (u - 1);
2330 }
2331 cur_arg++;
2332 }
2333 curproxy->bind_proc = set;
2334 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002335 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002336 if (curproxy == &defproxy) {
2337 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002340 }
2341
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002342 err = invalid_char(args[1]);
2343 if (err) {
2344 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2345 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002346 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002347 }
2348
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002349 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2350 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2351 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002354 }
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2357 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002361
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 if (*(args[1]) == 0) {
2363 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2364 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002368
Willy Tarreau67402132012-05-31 20:40:20 +02002369 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002370 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002371 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002372 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 curproxy->cookie_name = strdup(args[1]);
2374 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002375
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 cur_arg = 2;
2377 while (*(args[cur_arg])) {
2378 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002379 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002382 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002383 }
2384 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002385 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
2387 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002388 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
2390 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002391 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002393 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002394 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002395 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002397 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002399 else if (!strcmp(args[cur_arg], "httponly")) {
2400 curproxy->ck_opts |= PR_CK_HTTPONLY;
2401 }
2402 else if (!strcmp(args[cur_arg], "secure")) {
2403 curproxy->ck_opts |= PR_CK_SECURE;
2404 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002405 else if (!strcmp(args[cur_arg], "domain")) {
2406 if (!*args[cur_arg + 1]) {
2407 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2408 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002411 }
2412
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002413 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002414 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002415 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2416 " dots nor does not start with a dot."
2417 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002418 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002419 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002420 }
2421
2422 err = invalid_domainchar(args[cur_arg + 1]);
2423 if (err) {
2424 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2425 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002428 }
2429
Willy Tarreau68a897b2009-12-03 23:28:34 +01002430 if (!curproxy->cookie_domain) {
2431 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2432 } else {
2433 /* one domain was already specified, add another one by
2434 * building the string which will be returned along with
2435 * the cookie.
2436 */
2437 char *new_ptr;
2438 int new_len = strlen(curproxy->cookie_domain) +
2439 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2440 new_ptr = malloc(new_len);
2441 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2442 free(curproxy->cookie_domain);
2443 curproxy->cookie_domain = new_ptr;
2444 }
Willy Tarreau31936852010-10-06 16:59:56 +02002445 cur_arg++;
2446 }
2447 else if (!strcmp(args[cur_arg], "maxidle")) {
2448 unsigned int maxidle;
2449 const char *res;
2450
2451 if (!*args[cur_arg + 1]) {
2452 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2453 file, linenum, args[cur_arg]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457
2458 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2459 if (res) {
2460 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2461 file, linenum, *res, args[cur_arg]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465 curproxy->cookie_maxidle = maxidle;
2466 cur_arg++;
2467 }
2468 else if (!strcmp(args[cur_arg], "maxlife")) {
2469 unsigned int maxlife;
2470 const char *res;
2471
2472 if (!*args[cur_arg + 1]) {
2473 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2474 file, linenum, args[cur_arg]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
2479 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2480 if (res) {
2481 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2482 file, linenum, *res, args[cur_arg]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002487 cur_arg++;
2488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002490 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 +02002491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 }
2495 cur_arg++;
2496 }
Willy Tarreau67402132012-05-31 20:40:20 +02002497 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2499 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002501 }
2502
Willy Tarreau67402132012-05-31 20:40:20 +02002503 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2505 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002508
Willy Tarreau67402132012-05-31 20:40:20 +02002509 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002510 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2511 file, linenum);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002515 else if (!strcmp(args[0], "persist")) { /* persist */
2516 if (*(args[1]) == 0) {
2517 Alert("parsing [%s:%d] : missing persist method.\n",
2518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002521 }
2522
2523 if (!strncmp(args[1], "rdp-cookie", 10)) {
2524 curproxy->options2 |= PR_O2_RDPC_PRST;
2525
Emeric Brunb982a3d2010-01-04 15:45:53 +01002526 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002527 const char *beg, *end;
2528
2529 beg = args[1] + 11;
2530 end = strchr(beg, ')');
2531
2532 if (!end || end == beg) {
2533 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002537 }
2538
2539 free(curproxy->rdp_cookie_name);
2540 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2541 curproxy->rdp_cookie_len = end-beg;
2542 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002543 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002544 free(curproxy->rdp_cookie_name);
2545 curproxy->rdp_cookie_name = strdup("msts");
2546 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2547 }
2548 else { /* syntax */
2549 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002553 }
2554 }
2555 else {
2556 Alert("parsing [%s:%d] : unknown persist method.\n",
2557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002560 }
2561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002563 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002565 if (curproxy == &defproxy) {
2566 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002572 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002573
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002575 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002581 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 curproxy->appsession_name = strdup(args[1]);
2583 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2584 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002585 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2586 if (err) {
2587 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2588 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002591 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002592 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002593
Willy Tarreau51041c72007-09-09 21:56:53 +02002594 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2595 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_ABORT;
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002599
2600 cur_arg = 6;
2601 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002602 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2603 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002604 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002605 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002606 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002607 } else if (!strcmp(args[cur_arg], "prefix")) {
2608 curproxy->options2 |= PR_O2_AS_PFX;
2609 } else if (!strcmp(args[cur_arg], "mode")) {
2610 if (!*args[cur_arg + 1]) {
2611 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2612 file, linenum, args[0], args[cur_arg]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
2617 cur_arg++;
2618 if (!strcmp(args[cur_arg], "query-string")) {
2619 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2620 curproxy->options2 |= PR_O2_AS_M_QS;
2621 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2622 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2623 curproxy->options2 |= PR_O2_AS_M_PP;
2624 } else {
2625 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
2628 }
2629 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002630 cur_arg++;
2631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 } /* Url App Session */
2633 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002634 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002638 if (curproxy == &defproxy) {
2639 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644 if (*(args[4]) == 0) {
2645 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002650 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 curproxy->capture_name = strdup(args[2]);
2652 curproxy->capture_namelen = strlen(curproxy->capture_name);
2653 curproxy->capture_len = atol(args[4]);
2654 if (curproxy->capture_len >= CAPTURE_LEN) {
2655 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2656 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 curproxy->capture_len = CAPTURE_LEN - 1;
2659 }
2660 curproxy->to_log |= LW_COOKIE;
2661 }
2662 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2663 struct cap_hdr *hdr;
2664
2665 if (curproxy == &defproxy) {
2666 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 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670
2671 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2672 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2673 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 }
2677
2678 hdr = calloc(sizeof(struct cap_hdr), 1);
2679 hdr->next = curproxy->req_cap;
2680 hdr->name = strdup(args[3]);
2681 hdr->namelen = strlen(args[3]);
2682 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002683 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 hdr->index = curproxy->nb_req_cap++;
2685 curproxy->req_cap = hdr;
2686 curproxy->to_log |= LW_REQHDR;
2687 }
2688 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2689 struct cap_hdr *hdr;
2690
2691 if (curproxy == &defproxy) {
2692 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 +02002693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 }
2696
2697 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2698 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2699 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 }
2703 hdr = calloc(sizeof(struct cap_hdr), 1);
2704 hdr->next = curproxy->rsp_cap;
2705 hdr->name = strdup(args[3]);
2706 hdr->namelen = strlen(args[3]);
2707 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002708 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002709 hdr->index = curproxy->nb_rsp_cap++;
2710 curproxy->rsp_cap = hdr;
2711 curproxy->to_log |= LW_RSPHDR;
2712 }
2713 else {
2714 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 }
2719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002721 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002723
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 if (*(args[1]) == 0) {
2725 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 }
2730 curproxy->conn_retries = atol(args[1]);
2731 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002732 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002733 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002734
2735 if (curproxy == &defproxy) {
2736 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
Willy Tarreauff011f22011-01-06 17:51:27 +01002741 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 +01002742 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2743 file, linenum, args[0]);
2744 err_code |= ERR_WARN;
2745 }
2746
Willy Tarreauff011f22011-01-06 17:51:27 +01002747 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002748
Willy Tarreauff011f22011-01-06 17:51:27 +01002749 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002750 err_code |= ERR_ALERT | ERR_ABORT;
2751 goto out;
2752 }
2753
Willy Tarreauff011f22011-01-06 17:51:27 +01002754 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2755 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002756 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002757 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2758 /* set the header name and length into the proxy structure */
2759 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2760 err_code |= ERR_WARN;
2761
2762 if (!*args[1]) {
2763 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2764 file, linenum, args[0]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768
2769 /* set the desired header name */
2770 free(curproxy->server_id_hdr_name);
2771 curproxy->server_id_hdr_name = strdup(args[1]);
2772 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2773 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002774 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002775 if (curproxy == &defproxy) {
2776 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002779 }
2780
Willy Tarreauef6494c2010-01-28 17:12:36 +01002781 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002782 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2783 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002786 }
2787
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002788 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2789 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2790 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002793 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002794
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002795 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002796 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002797 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002798 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002799 struct redirect_rule *rule;
2800 int cur_arg;
2801 int type = REDIRECT_TYPE_NONE;
2802 int code = 302;
2803 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002804 char *cookie = NULL;
2805 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002806 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002807
Cyril Bonté99ed3272010-01-24 23:29:44 +01002808 if (curproxy == &defproxy) {
2809 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
2812 }
2813
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002814 cur_arg = 1;
2815 while (*(args[cur_arg])) {
2816 if (!strcmp(args[cur_arg], "location")) {
2817 if (!*args[cur_arg + 1]) {
2818 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2819 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002822 }
2823
2824 type = REDIRECT_TYPE_LOCATION;
2825 cur_arg++;
2826 destination = args[cur_arg];
2827 }
2828 else if (!strcmp(args[cur_arg], "prefix")) {
2829 if (!*args[cur_arg + 1]) {
2830 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2831 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002834 }
2835
2836 type = REDIRECT_TYPE_PREFIX;
2837 cur_arg++;
2838 destination = args[cur_arg];
2839 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002840 else if (!strcmp(args[cur_arg], "set-cookie")) {
2841 if (!*args[cur_arg + 1]) {
2842 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2843 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002846 }
2847
2848 cur_arg++;
2849 cookie = args[cur_arg];
2850 cookie_set = 1;
2851 }
2852 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2853 if (!*args[cur_arg + 1]) {
2854 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2855 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002858 }
2859
2860 cur_arg++;
2861 cookie = args[cur_arg];
2862 cookie_set = 0;
2863 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002864 else if (!strcmp(args[cur_arg],"code")) {
2865 if (!*args[cur_arg + 1]) {
2866 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002870 }
2871 cur_arg++;
2872 code = atol(args[cur_arg]);
2873 if (code < 301 || code > 303) {
2874 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2875 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002878 }
2879 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002880 else if (!strcmp(args[cur_arg],"drop-query")) {
2881 flags |= REDIRECT_FLAG_DROP_QS;
2882 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002883 else if (!strcmp(args[cur_arg],"append-slash")) {
2884 flags |= REDIRECT_FLAG_APPEND_SLASH;
2885 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002886 else if (strcmp(args[cur_arg], "if") == 0 ||
2887 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002888 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002889 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002890 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2891 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002895 break;
2896 }
2897 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002898 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002899 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002902 }
2903 cur_arg++;
2904 }
2905
2906 if (type == REDIRECT_TYPE_NONE) {
2907 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002911 }
2912
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002913 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2914 rule->cond = cond;
2915 rule->rdr_str = strdup(destination);
2916 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002917 if (cookie) {
2918 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002919 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002920 */
2921 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002922 if (cookie_set) {
2923 rule->cookie_str = malloc(rule->cookie_len + 10);
2924 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2925 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2926 rule->cookie_len += 9;
2927 } else {
2928 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002929 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002930 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2931 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002932 }
2933 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002934 rule->type = type;
2935 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002936 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002937 LIST_INIT(&rule->list);
2938 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002939 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2940 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002941 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002942 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002943 struct switching_rule *rule;
2944
Willy Tarreaub099aca2008-10-12 17:26:37 +02002945 if (curproxy == &defproxy) {
2946 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002949 }
2950
Willy Tarreau55ea7572007-06-17 19:56:27 +02002951 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002952 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002953
2954 if (*(args[1]) == 0) {
2955 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002958 }
2959
Willy Tarreauef6494c2010-01-28 17:12:36 +01002960 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002961 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002965 }
2966
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002967 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2968 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2969 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002972 }
2973
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002974 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002975
Willy Tarreau55ea7572007-06-17 19:56:27 +02002976 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2977 rule->cond = cond;
2978 rule->be.name = strdup(args[1]);
2979 LIST_INIT(&rule->list);
2980 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2981 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002982 else if (strcmp(args[0], "use-server") == 0) {
2983 struct server_rule *rule;
2984
2985 if (curproxy == &defproxy) {
2986 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990
2991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2992 err_code |= ERR_WARN;
2993
2994 if (*(args[1]) == 0) {
2995 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
3000 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3001 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3002 file, linenum, args[0]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003007 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3008 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3009 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
3013
3014 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3015
3016 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3017 rule->cond = cond;
3018 rule->srv.name = strdup(args[1]);
3019 LIST_INIT(&rule->list);
3020 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3021 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3022 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003023 else if ((!strcmp(args[0], "force-persist")) ||
3024 (!strcmp(args[0], "ignore-persist"))) {
3025 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003026
3027 if (curproxy == &defproxy) {
3028 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032
3033 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3034 err_code |= ERR_WARN;
3035
Willy Tarreauef6494c2010-01-28 17:12:36 +01003036 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003037 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3038 file, linenum, args[0]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
3041 }
3042
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003043 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3044 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3045 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
3048 }
3049
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003050 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003051
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003052 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003053 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003054 if (!strcmp(args[0], "force-persist")) {
3055 rule->type = PERSIST_TYPE_FORCE;
3056 } else {
3057 rule->type = PERSIST_TYPE_IGNORE;
3058 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003059 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003060 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003061 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 else if (!strcmp(args[0], "stick-table")) {
3063 int myidx = 1;
3064
Emeric Brun32da3c42010-09-23 18:39:19 +02003065 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 curproxy->table.type = (unsigned int)-1;
3067 while (*args[myidx]) {
3068 const char *err;
3069
3070 if (strcmp(args[myidx], "size") == 0) {
3071 myidx++;
3072 if (!*(args[myidx])) {
3073 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3074 file, linenum, args[myidx-1]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3079 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3080 file, linenum, *err, args[myidx-1]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003084 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003085 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003086 else if (strcmp(args[myidx], "peers") == 0) {
3087 myidx++;
3088 if (!*(args[myidx])) {
3089 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3090 file, linenum, args[myidx-1]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094 curproxy->table.peers.name = strdup(args[myidx++]);
3095 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003096 else if (strcmp(args[myidx], "expire") == 0) {
3097 myidx++;
3098 if (!*(args[myidx])) {
3099 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3100 file, linenum, args[myidx-1]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3105 if (err) {
3106 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3107 file, linenum, *err, args[myidx-1]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003112 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003113 }
3114 else if (strcmp(args[myidx], "nopurge") == 0) {
3115 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003116 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003117 }
3118 else if (strcmp(args[myidx], "type") == 0) {
3119 myidx++;
3120 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3121 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3122 file, linenum, args[myidx]);
3123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
3125 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003126 /* myidx already points to next arg */
3127 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003128 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003129 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003130 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003131
3132 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003133 nw = args[myidx];
3134 while (*nw) {
3135 /* the "store" keyword supports a comma-separated list */
3136 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003137 sa = NULL; /* store arg */
3138 while (*nw && *nw != ',') {
3139 if (*nw == '(') {
3140 *nw = 0;
3141 sa = ++nw;
3142 while (*nw != ')') {
3143 if (!*nw) {
3144 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3145 file, linenum, args[0], cw);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149 nw++;
3150 }
3151 *nw = '\0';
3152 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003153 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003154 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003155 if (*nw)
3156 *nw++ = '\0';
3157 type = stktable_get_data_type(cw);
3158 if (type < 0) {
3159 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3160 file, linenum, args[0], cw);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
Willy Tarreauac782882010-06-20 10:41:54 +02003164
3165 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3166 switch (err) {
3167 case PE_NONE: break;
3168 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003169 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3170 file, linenum, args[0], cw);
3171 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003172 break;
3173
3174 case PE_ARG_MISSING:
3175 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3176 file, linenum, args[0], cw);
3177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179
3180 case PE_ARG_NOT_USED:
3181 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3182 file, linenum, args[0], cw);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
3185
3186 default:
3187 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3188 file, linenum, args[0], cw);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003191 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003192 }
3193 myidx++;
3194 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003195 else {
3196 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3197 file, linenum, args[myidx]);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003200 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003201 }
3202
3203 if (!curproxy->table.size) {
3204 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3205 file, linenum);
3206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209
3210 if (curproxy->table.type == (unsigned int)-1) {
3211 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3212 file, linenum);
3213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
3216 }
3217 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003218 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003219 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003220 int myidx = 0;
3221 const char *name = NULL;
3222 int flags;
3223
3224 if (curproxy == &defproxy) {
3225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228 }
3229
3230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3231 err_code |= ERR_WARN;
3232 goto out;
3233 }
3234
3235 myidx++;
3236 if ((strcmp(args[myidx], "store") == 0) ||
3237 (strcmp(args[myidx], "store-request") == 0)) {
3238 myidx++;
3239 flags = STK_IS_STORE;
3240 }
3241 else if (strcmp(args[myidx], "store-response") == 0) {
3242 myidx++;
3243 flags = STK_IS_STORE | STK_ON_RSP;
3244 }
3245 else if (strcmp(args[myidx], "match") == 0) {
3246 myidx++;
3247 flags = STK_IS_MATCH;
3248 }
3249 else if (strcmp(args[myidx], "on") == 0) {
3250 myidx++;
3251 flags = STK_IS_MATCH | STK_IS_STORE;
3252 }
3253 else {
3254 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258
3259 if (*(args[myidx]) == 0) {
3260 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
3263 }
3264
David du Colombier7af46052012-05-16 14:16:48 +02003265 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003266 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003267 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271
3272 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003273 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003274 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3275 file, linenum, args[0], expr->fetch->kw);
3276 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003277 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003278 goto out;
3279 }
3280 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003281 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003282 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3283 file, linenum, args[0], expr->fetch->kw);
3284 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003285 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003286 goto out;
3287 }
3288 }
3289
3290 if (strcmp(args[myidx], "table") == 0) {
3291 myidx++;
3292 name = args[myidx++];
3293 }
3294
Willy Tarreauef6494c2010-01-28 17:12:36 +01003295 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003296 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3297 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3298 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003299 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003300 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003301 goto out;
3302 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003303 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003304 else if (*(args[myidx])) {
3305 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3306 file, linenum, args[0], args[myidx]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003308 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003309 goto out;
3310 }
Emeric Brun97679e72010-09-23 17:56:44 +02003311 if (flags & STK_ON_RSP)
3312 err_code |= warnif_cond_requires_req(cond, file, linenum);
3313 else
3314 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003315
Emeric Brunb982a3d2010-01-04 15:45:53 +01003316 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3317 rule->cond = cond;
3318 rule->expr = expr;
3319 rule->flags = flags;
3320 rule->table.name = name ? strdup(name) : NULL;
3321 LIST_INIT(&rule->list);
3322 if (flags & STK_ON_RSP)
3323 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3324 else
3325 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003330
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3332 curproxy->uri_auth = NULL; /* we must detach from the default config */
3333
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003334 if (!*args[1]) {
3335 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003336 } else if (!strcmp(args[1], "admin")) {
3337 struct stats_admin_rule *rule;
3338
3339 if (curproxy == &defproxy) {
3340 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
3343 }
3344
3345 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3346 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3347 err_code |= ERR_ALERT | ERR_ABORT;
3348 goto out;
3349 }
3350
3351 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3352 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3353 file, linenum, args[0], args[1]);
3354 err_code |= ERR_ALERT | ERR_FATAL;
3355 goto out;
3356 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003357 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3358 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3359 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363
3364 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3365
3366 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3367 rule->cond = cond;
3368 LIST_INIT(&rule->list);
3369 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370 } else if (!strcmp(args[1], "uri")) {
3371 if (*(args[2]) == 0) {
3372 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3376 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003377 err_code |= ERR_ALERT | ERR_ABORT;
3378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380 } else if (!strcmp(args[1], "realm")) {
3381 if (*(args[2]) == 0) {
3382 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003387 err_code |= ERR_ALERT | ERR_ABORT;
3388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003390 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003391 unsigned interval;
3392
3393 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3394 if (err) {
3395 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3396 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003399 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_ABORT;
3402 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003403 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003404 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003405 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003406
3407 if (curproxy == &defproxy) {
3408 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3409 err_code |= ERR_ALERT | ERR_FATAL;
3410 goto out;
3411 }
3412
3413 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3414 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3415 err_code |= ERR_ALERT | ERR_ABORT;
3416 goto out;
3417 }
3418
Willy Tarreauff011f22011-01-06 17:51:27 +01003419 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3420 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003421 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3422 file, linenum, args[0]);
3423 err_code |= ERR_WARN;
3424 }
3425
Willy Tarreauff011f22011-01-06 17:51:27 +01003426 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003427
Willy Tarreauff011f22011-01-06 17:51:27 +01003428 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003429 err_code |= ERR_ALERT | ERR_ABORT;
3430 goto out;
3431 }
3432
Willy Tarreauff011f22011-01-06 17:51:27 +01003433 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3434 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003435
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 } else if (!strcmp(args[1], "auth")) {
3437 if (*(args[2]) == 0) {
3438 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3442 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_ABORT;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
3446 } else if (!strcmp(args[1], "scope")) {
3447 if (*(args[2]) == 0) {
3448 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3452 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_ALERT | ERR_ABORT;
3454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455 }
3456 } else if (!strcmp(args[1], "enable")) {
3457 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3458 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_ABORT;
3460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003462 } else if (!strcmp(args[1], "hide-version")) {
3463 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3464 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003465 err_code |= ERR_ALERT | ERR_ABORT;
3466 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003467 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003468 } else if (!strcmp(args[1], "show-legends")) {
3469 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3470 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3471 err_code |= ERR_ALERT | ERR_ABORT;
3472 goto out;
3473 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003474 } else if (!strcmp(args[1], "show-node")) {
3475
3476 if (*args[2]) {
3477 int i;
3478 char c;
3479
3480 for (i=0; args[2][i]; i++) {
3481 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003482 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3483 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003484 break;
3485 }
3486
3487 if (!i || args[2][i]) {
3488 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3489 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3490 file, linenum, args[0], args[1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494 }
3495
3496 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3497 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3498 err_code |= ERR_ALERT | ERR_ABORT;
3499 goto out;
3500 }
3501 } else if (!strcmp(args[1], "show-desc")) {
3502 char *desc = NULL;
3503
3504 if (*args[2]) {
3505 int i, len=0;
3506 char *d;
3507
3508 for(i=2; *args[i]; i++)
3509 len += strlen(args[i])+1;
3510
3511 desc = d = (char *)calloc(1, len);
3512
3513 d += sprintf(d, "%s", args[2]);
3514 for(i=3; *args[i]; i++)
3515 d += sprintf(d, " %s", args[i]);
3516 }
3517
3518 if (!*args[2] && !global.desc)
3519 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3520 file, linenum, args[1]);
3521 else {
3522 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3523 free(desc);
3524 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3525 err_code |= ERR_ALERT | ERR_ABORT;
3526 goto out;
3527 }
3528 free(desc);
3529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003531stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003532 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 +01003533 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537 }
3538 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003539 int optnum;
3540
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003541 if (*(args[1]) == '\0') {
3542 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3543 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003547
3548 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3549 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003550 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3551 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3552 file, linenum, cfg_opts[optnum].name);
3553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
3555 }
Willy Tarreau93893792009-07-23 13:19:11 +02003556 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3557 err_code |= ERR_WARN;
3558 goto out;
3559 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003560
Willy Tarreau3842f002009-06-14 11:39:52 +02003561 curproxy->no_options &= ~cfg_opts[optnum].val;
3562 curproxy->options &= ~cfg_opts[optnum].val;
3563
3564 switch (kwm) {
3565 case KWM_STD:
3566 curproxy->options |= cfg_opts[optnum].val;
3567 break;
3568 case KWM_NO:
3569 curproxy->no_options |= cfg_opts[optnum].val;
3570 break;
3571 case KWM_DEF: /* already cleared */
3572 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003573 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003574
Willy Tarreau93893792009-07-23 13:19:11 +02003575 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003576 }
3577 }
3578
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003579 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3580 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003581 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3582 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3583 file, linenum, cfg_opts2[optnum].name);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
Willy Tarreau93893792009-07-23 13:19:11 +02003587 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3588 err_code |= ERR_WARN;
3589 goto out;
3590 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003591
Willy Tarreau3842f002009-06-14 11:39:52 +02003592 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3593 curproxy->options2 &= ~cfg_opts2[optnum].val;
3594
3595 switch (kwm) {
3596 case KWM_STD:
3597 curproxy->options2 |= cfg_opts2[optnum].val;
3598 break;
3599 case KWM_NO:
3600 curproxy->no_options2 |= cfg_opts2[optnum].val;
3601 break;
3602 case KWM_DEF: /* already cleared */
3603 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003604 }
Willy Tarreau93893792009-07-23 13:19:11 +02003605 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003606 }
3607 }
3608
Willy Tarreau3842f002009-06-14 11:39:52 +02003609 if (kwm != KWM_STD) {
3610 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003611 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003614 }
3615
Emeric Brun3a058f32009-06-30 18:26:00 +02003616 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003617 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003619 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003620 if (*(args[2]) != '\0') {
3621 if (!strcmp(args[2], "clf")) {
3622 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003623 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003624 } else {
3625 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_ALERT | ERR_FATAL;
3627 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003628 }
3629 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003630 if (curproxy->logformat_string != default_http_log_format &&
3631 curproxy->logformat_string != default_tcp_log_format &&
3632 curproxy->logformat_string != clf_http_log_format)
3633 free(curproxy->logformat_string);
3634 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003635 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003636 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003638 if (curproxy->logformat_string != default_http_log_format &&
3639 curproxy->logformat_string != default_tcp_log_format &&
3640 curproxy->logformat_string != clf_http_log_format)
3641 free(curproxy->logformat_string);
3642 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644 else if (!strcmp(args[1], "tcpka")) {
3645 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003646 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003648
3649 if (curproxy->cap & PR_CAP_FE)
3650 curproxy->options |= PR_O_TCP_CLI_KA;
3651 if (curproxy->cap & PR_CAP_BE)
3652 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653 }
3654 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003655 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003656 err_code |= ERR_WARN;
3657
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003659 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003660 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003661 curproxy->options2 &= ~PR_O2_CHK_ANY;
3662 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003663 if (!*args[2]) { /* no argument */
3664 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3665 curproxy->check_len = strlen(DEF_CHECK_REQ);
3666 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003667 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 curproxy->check_req = (char *)malloc(reqlen);
3669 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003670 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003672 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 if (*args[4])
3674 reqlen += strlen(args[4]);
3675 else
3676 reqlen += strlen("HTTP/1.0");
3677
3678 curproxy->check_req = (char *)malloc(reqlen);
3679 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003680 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003681 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003682 }
3683 else if (!strcmp(args[1], "ssl-hello-chk")) {
3684 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003685 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003687
Willy Tarreaua534fea2008-08-03 12:19:50 +02003688 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003689 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003690 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003691 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 }
Willy Tarreau23677902007-05-08 23:50:35 +02003693 else if (!strcmp(args[1], "smtpchk")) {
3694 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003695 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003696 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003697 curproxy->options2 &= ~PR_O2_CHK_ANY;
3698 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003699
3700 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3701 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3702 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3703 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3704 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3705 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3706 curproxy->check_req = (char *)malloc(reqlen);
3707 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3708 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3709 } else {
3710 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3711 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3712 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3713 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3714 }
3715 }
3716 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003717 else if (!strcmp(args[1], "pgsql-check")) {
3718 /* use PostgreSQL request to check servers' health */
3719 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3720 err_code |= ERR_WARN;
3721
3722 free(curproxy->check_req);
3723 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003724 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003725 curproxy->options2 |= PR_O2_PGSQL_CHK;
3726
3727 if (*(args[2])) {
3728 int cur_arg = 2;
3729
3730 while (*(args[cur_arg])) {
3731 if (strcmp(args[cur_arg], "user") == 0) {
3732 char * packet;
3733 uint32_t packet_len;
3734 uint32_t pv;
3735
3736 /* suboption header - needs additional argument for it */
3737 if (*(args[cur_arg+1]) == 0) {
3738 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3739 file, linenum, args[0], args[1], args[cur_arg]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743
3744 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3745 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3746 pv = htonl(0x30000); /* protocol version 3.0 */
3747
3748 packet = (char*) calloc(1, packet_len);
3749
3750 memcpy(packet + 4, &pv, 4);
3751
3752 /* copy "user" */
3753 memcpy(packet + 8, "user", 4);
3754
3755 /* copy username */
3756 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3757
3758 free(curproxy->check_req);
3759 curproxy->check_req = packet;
3760 curproxy->check_len = packet_len;
3761
3762 packet_len = htonl(packet_len);
3763 memcpy(packet, &packet_len, 4);
3764 cur_arg += 2;
3765 } else {
3766 /* unknown suboption - catchall */
3767 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3768 file, linenum, args[0], args[1]);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772 } /* end while loop */
3773 }
3774 }
3775
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003776 else if (!strcmp(args[1], "redis-check")) {
3777 /* use REDIS PING request to check servers' health */
3778 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3779 err_code |= ERR_WARN;
3780
3781 free(curproxy->check_req);
3782 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003783 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003784 curproxy->options2 |= PR_O2_REDIS_CHK;
3785
3786 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3787 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3788 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3789 }
3790
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003791 else if (!strcmp(args[1], "mysql-check")) {
3792 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3794 err_code |= ERR_WARN;
3795
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003796 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003797 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003798 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003799 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003800
3801 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3802 * const char mysql40_client_auth_pkt[] = {
3803 * "\x0e\x00\x00" // packet length
3804 * "\x01" // packet number
3805 * "\x00\x00" // client capabilities
3806 * "\x00\x00\x01" // max packet
3807 * "haproxy\x00" // username (null terminated string)
3808 * "\x00" // filler (always 0x00)
3809 * "\x01\x00\x00" // packet length
3810 * "\x00" // packet number
3811 * "\x01" // COM_QUIT command
3812 * };
3813 */
3814
3815 if (*(args[2])) {
3816 int cur_arg = 2;
3817
3818 while (*(args[cur_arg])) {
3819 if (strcmp(args[cur_arg], "user") == 0) {
3820 char *mysqluser;
3821 int packetlen, reqlen, userlen;
3822
3823 /* suboption header - needs additional argument for it */
3824 if (*(args[cur_arg+1]) == 0) {
3825 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3826 file, linenum, args[0], args[1], args[cur_arg]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830 mysqluser = args[cur_arg + 1];
3831 userlen = strlen(mysqluser);
3832 packetlen = userlen + 7;
3833 reqlen = packetlen + 9;
3834
3835 free(curproxy->check_req);
3836 curproxy->check_req = (char *)calloc(1, reqlen);
3837 curproxy->check_len = reqlen;
3838
3839 snprintf(curproxy->check_req, 4, "%c%c%c",
3840 ((unsigned char) packetlen & 0xff),
3841 ((unsigned char) (packetlen >> 8) & 0xff),
3842 ((unsigned char) (packetlen >> 16) & 0xff));
3843
3844 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003845 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003846 curproxy->check_req[8] = 1;
3847 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3848 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3849 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3850 cur_arg += 2;
3851 } else {
3852 /* unknown suboption - catchall */
3853 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3854 file, linenum, args[0], args[1]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858 } /* end while loop */
3859 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003860 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003861 else if (!strcmp(args[1], "ldap-check")) {
3862 /* use LDAP request to check servers' health */
3863 free(curproxy->check_req);
3864 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003865 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003866 curproxy->options2 |= PR_O2_LDAP_CHK;
3867
3868 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3869 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3870 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3871 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003872 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003873 int cur_arg;
3874
3875 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3876 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003877 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003878
Willy Tarreau87cf5142011-08-19 22:57:24 +02003879 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003880
3881 free(curproxy->fwdfor_hdr_name);
3882 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3883 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3884
3885 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3886 cur_arg = 2;
3887 while (*(args[cur_arg])) {
3888 if (!strcmp(args[cur_arg], "except")) {
3889 /* suboption except - needs additional argument for it */
3890 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3891 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3892 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003895 }
3896 /* flush useless bits */
3897 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003898 cur_arg += 2;
3899 } else if (!strcmp(args[cur_arg], "header")) {
3900 /* suboption header - needs additional argument for it */
3901 if (*(args[cur_arg+1]) == 0) {
3902 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3903 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003906 }
3907 free(curproxy->fwdfor_hdr_name);
3908 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3909 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3910 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003911 } else if (!strcmp(args[cur_arg], "if-none")) {
3912 curproxy->options &= ~PR_O_FF_ALWAYS;
3913 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003914 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003915 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003916 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003917 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003920 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003921 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003922 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003923 else if (!strcmp(args[1], "originalto")) {
3924 int cur_arg;
3925
3926 /* insert x-original-to field, but not for the IP address listed as an except.
3927 * set default options (ie: bitfield, header name, etc)
3928 */
3929
3930 curproxy->options |= PR_O_ORGTO;
3931
3932 free(curproxy->orgto_hdr_name);
3933 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3934 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3935
Willy Tarreau87cf5142011-08-19 22:57:24 +02003936 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003937 cur_arg = 2;
3938 while (*(args[cur_arg])) {
3939 if (!strcmp(args[cur_arg], "except")) {
3940 /* suboption except - needs additional argument for it */
3941 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3942 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3943 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003946 }
3947 /* flush useless bits */
3948 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3949 cur_arg += 2;
3950 } else if (!strcmp(args[cur_arg], "header")) {
3951 /* suboption header - needs additional argument for it */
3952 if (*(args[cur_arg+1]) == 0) {
3953 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3954 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003957 }
3958 free(curproxy->orgto_hdr_name);
3959 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3960 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3961 cur_arg += 2;
3962 } else {
3963 /* unknown suboption - catchall */
3964 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3965 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003968 }
3969 } /* end while loop */
3970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971 else {
3972 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 }
Willy Tarreau93893792009-07-23 13:19:11 +02003976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003978 else if (!strcmp(args[0], "default_backend")) {
3979 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003980 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003981
3982 if (*(args[1]) == 0) {
3983 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003986 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003987 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003988 curproxy->defbe.name = strdup(args[1]);
3989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003991 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003993
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003994 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3995 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 /* enable reconnections to dispatch */
3998 curproxy->options |= PR_O_REDISP;
3999 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004000 else if (!strcmp(args[0], "http-check")) {
4001 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004003
4004 if (strcmp(args[1], "disable-on-404") == 0) {
4005 /* enable a graceful server shutdown on an HTTP 404 response */
4006 curproxy->options |= PR_O_DISABLE404;
4007 }
Willy Tarreauef781042010-01-27 11:53:01 +01004008 else if (strcmp(args[1], "send-state") == 0) {
4009 /* enable emission of the apparent state of a server in HTTP checks */
4010 curproxy->options2 |= PR_O2_CHK_SNDST;
4011 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004012 else if (strcmp(args[1], "expect") == 0) {
4013 const char *ptr_arg;
4014 int cur_arg;
4015
4016 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4017 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021
4022 cur_arg = 2;
4023 /* consider exclamation marks, sole or at the beginning of a word */
4024 while (*(ptr_arg = args[cur_arg])) {
4025 while (*ptr_arg == '!') {
4026 curproxy->options2 ^= PR_O2_EXP_INV;
4027 ptr_arg++;
4028 }
4029 if (*ptr_arg)
4030 break;
4031 cur_arg++;
4032 }
4033 /* now ptr_arg points to the beginning of a word past any possible
4034 * exclamation mark, and cur_arg is the argument which holds this word.
4035 */
4036 if (strcmp(ptr_arg, "status") == 0) {
4037 if (!*(args[cur_arg + 1])) {
4038 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4039 file, linenum, args[0], args[1], ptr_arg);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004044 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004045 curproxy->expect_str = strdup(args[cur_arg + 1]);
4046 }
4047 else if (strcmp(ptr_arg, "string") == 0) {
4048 if (!*(args[cur_arg + 1])) {
4049 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4050 file, linenum, args[0], args[1], ptr_arg);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004055 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004056 curproxy->expect_str = strdup(args[cur_arg + 1]);
4057 }
4058 else if (strcmp(ptr_arg, "rstatus") == 0) {
4059 if (!*(args[cur_arg + 1])) {
4060 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4061 file, linenum, args[0], args[1], ptr_arg);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004066 free(curproxy->expect_str);
4067 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4068 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004069 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4070 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4071 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4072 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 }
4077 else if (strcmp(ptr_arg, "rstring") == 0) {
4078 if (!*(args[cur_arg + 1])) {
4079 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4080 file, linenum, args[0], args[1], ptr_arg);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004085 free(curproxy->expect_str);
4086 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4087 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004088 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4089 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4090 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4091 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095 }
4096 else {
4097 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4098 file, linenum, args[0], args[1], ptr_arg);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004103 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004104 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 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004107 }
4108 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004109 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004110 if (curproxy == &defproxy) {
4111 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004114 }
4115
Willy Tarreaub80c2302007-11-30 20:51:32 +01004116 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004118
4119 if (strcmp(args[1], "fail") == 0) {
4120 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004121 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004122 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4123 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004126 }
4127
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004128 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4129 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4130 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004133 }
4134 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4135 }
4136 else {
4137 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004140 }
4141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142#ifdef TPROXY
4143 else if (!strcmp(args[0], "transparent")) {
4144 /* enable transparent proxy connections */
4145 curproxy->options |= PR_O_TRANSP;
4146 }
4147#endif
4148 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004149 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004151
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 if (*(args[1]) == 0) {
4153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 }
4157 curproxy->maxconn = atol(args[1]);
4158 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004159 else if (!strcmp(args[0], "backlog")) { /* backlog */
4160 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004162
4163 if (*(args[1]) == 0) {
4164 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004165 err_code |= ERR_ALERT | ERR_FATAL;
4166 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004167 }
4168 curproxy->backlog = atol(args[1]);
4169 }
Willy Tarreau86034312006-12-29 00:10:33 +01004170 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004171 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004173
Willy Tarreau86034312006-12-29 00:10:33 +01004174 if (*(args[1]) == 0) {
4175 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004178 }
4179 curproxy->fullconn = atol(args[1]);
4180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4182 if (*(args[1]) == 0) {
4183 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004187 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4188 if (err) {
4189 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4190 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004193 }
4194 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 }
4196 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004197 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198 if (curproxy == &defproxy) {
4199 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004203 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004204 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004205
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206 if (strchr(args[1], ':') == NULL) {
4207 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004210 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004211 sk = str2sa(args[1]);
4212 if (!sk) {
4213 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004218 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 }
4220 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004221 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004223
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004224 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4225 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004230 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4231 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4232 err_code |= ERR_WARN;
4233
4234 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4235 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4236 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4237 }
4238 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4239 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4240 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4241 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004242 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4243 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4244 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4245 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004246 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004247 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004252 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004254 char *rport, *raddr;
4255 short realport = 0;
4256 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004258 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004262 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004263 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004264 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265
4266 if (!*args[2]) {
4267 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004272
4273 err = invalid_char(args[1]);
4274 if (err) {
4275 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4276 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004279 }
4280
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004281 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004282 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004283
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004284 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4285 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4286 err_code |= ERR_ALERT | ERR_ABORT;
4287 goto out;
4288 }
4289
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004290 /* the servers are linked backwards first */
4291 newsrv->next = curproxy->srv;
4292 curproxy->srv = newsrv;
4293 newsrv->proxy = curproxy;
4294 newsrv->conf.file = file;
4295 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296
Simon Hormanaf514952011-06-21 14:34:57 +09004297 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004298 LIST_INIT(&newsrv->pendconns);
4299 do_check = 0;
4300 newsrv->state = SRV_RUNNING; /* early server setup */
4301 newsrv->last_change = now.tv_sec;
4302 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004304 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004305 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004306 * - IP: => port=+0, relative
4307 * - IP:N => port=N, absolute
4308 * - IP:+N => port=+N, relative
4309 * - IP:-N => port=-N, relative
4310 */
4311 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004312 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004313 if (rport) {
4314 *rport++ = 0;
4315 realport = atol(rport);
4316 if (!isdigit((unsigned char)*rport))
4317 newsrv->state |= SRV_MAPPORTS;
4318 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004319 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004320
Willy Tarreaufab5a432011-03-04 15:31:53 +01004321 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004322 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004323 if (!sk) {
4324 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
4327 }
4328 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004329 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004330 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004331
4332 if (!sk) {
4333 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4334 file, linenum, newsrv->addr.ss_family, args[2]);
4335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
4337 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004338 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004339
4340 newsrv->check_port = curproxy->defsrv.check_port;
4341 newsrv->inter = curproxy->defsrv.inter;
4342 newsrv->fastinter = curproxy->defsrv.fastinter;
4343 newsrv->downinter = curproxy->defsrv.downinter;
4344 newsrv->rise = curproxy->defsrv.rise;
4345 newsrv->fall = curproxy->defsrv.fall;
4346 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4347 newsrv->minconn = curproxy->defsrv.minconn;
4348 newsrv->maxconn = curproxy->defsrv.maxconn;
4349 newsrv->slowstart = curproxy->defsrv.slowstart;
4350 newsrv->onerror = curproxy->defsrv.onerror;
4351 newsrv->consecutive_errors_limit
4352 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004353#ifdef OPENSSL
4354 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4355#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004356 newsrv->uweight = newsrv->iweight
4357 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004358
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004359 newsrv->curfd = -1; /* no health-check in progress */
4360 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004361
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004362 cur_arg = 3;
4363 } else {
4364 newsrv = &curproxy->defsrv;
4365 cur_arg = 1;
4366 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004367
Willy Tarreaubaaee002006-06-26 02:48:02 +02004368 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004369 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004370 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004371
4372 if (!*args[cur_arg + 1]) {
4373 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4374 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004377 }
4378
4379 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004380 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004381
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004382 if (newsrv->puid <= 0) {
4383 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004384 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004387 }
4388
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004389 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4390 if (node) {
4391 struct server *target = container_of(node, struct server, conf.id);
4392 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4393 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
4396 }
4397 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004398 cur_arg += 2;
4399 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004400 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401 newsrv->cookie = strdup(args[cur_arg + 1]);
4402 newsrv->cklen = strlen(args[cur_arg + 1]);
4403 cur_arg += 2;
4404 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004405 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004406 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4407 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4408 cur_arg += 2;
4409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004410 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004411 if (!*args[cur_arg + 1]) {
4412 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4413 file, linenum, args[cur_arg]);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
4417
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004419 if (newsrv->rise <= 0) {
4420 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4421 file, linenum, args[cur_arg]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425
Willy Tarreau96839092010-03-29 10:02:24 +02004426 if (newsrv->health)
4427 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 cur_arg += 2;
4429 }
4430 else if (!strcmp(args[cur_arg], "fall")) {
4431 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004432
4433 if (!*args[cur_arg + 1]) {
4434 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4435 file, linenum, args[cur_arg]);
4436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
4438 }
4439
4440 if (newsrv->fall <= 0) {
4441 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4442 file, linenum, args[cur_arg]);
4443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
4445 }
4446
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 cur_arg += 2;
4448 }
4449 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004450 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4451 if (err) {
4452 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4453 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004456 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004457 if (val <= 0) {
4458 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4459 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004462 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004463 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 cur_arg += 2;
4465 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004466 else if (!strcmp(args[cur_arg], "fastinter")) {
4467 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4468 if (err) {
4469 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4470 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004473 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004474 if (val <= 0) {
4475 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4476 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004479 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004480 newsrv->fastinter = val;
4481 cur_arg += 2;
4482 }
4483 else if (!strcmp(args[cur_arg], "downinter")) {
4484 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4485 if (err) {
4486 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4487 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004490 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004491 if (val <= 0) {
4492 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4493 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004496 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004497 newsrv->downinter = val;
4498 cur_arg += 2;
4499 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004500 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004501 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004502 if (!sk) {
4503 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
4507 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004508 cur_arg += 2;
4509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 else if (!strcmp(args[cur_arg], "port")) {
4511 newsrv->check_port = atol(args[cur_arg + 1]);
4512 cur_arg += 2;
4513 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004514 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 newsrv->state |= SRV_BACKUP;
4516 cur_arg ++;
4517 }
Simon Hormanfa461682011-06-25 09:39:49 +09004518 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4519 newsrv->state |= SRV_NON_STICK;
4520 cur_arg ++;
4521 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004522 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4523 newsrv->state |= SRV_SEND_PROXY;
4524 cur_arg ++;
4525 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004526 else if (!strcmp(args[cur_arg], "weight")) {
4527 int w;
4528 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004529 if (w < 0 || w > 256) {
4530 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004535 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536 cur_arg += 2;
4537 }
4538 else if (!strcmp(args[cur_arg], "minconn")) {
4539 newsrv->minconn = atol(args[cur_arg + 1]);
4540 cur_arg += 2;
4541 }
4542 else if (!strcmp(args[cur_arg], "maxconn")) {
4543 newsrv->maxconn = atol(args[cur_arg + 1]);
4544 cur_arg += 2;
4545 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004546 else if (!strcmp(args[cur_arg], "maxqueue")) {
4547 newsrv->maxqueue = atol(args[cur_arg + 1]);
4548 cur_arg += 2;
4549 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004550 else if (!strcmp(args[cur_arg], "slowstart")) {
4551 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004552 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004553 if (err) {
4554 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4555 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004558 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004559 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004560 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4561 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004564 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004565 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004566 cur_arg += 2;
4567 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004568 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004569
4570 if (!*args[cur_arg + 1]) {
4571 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4572 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004575 }
4576
4577 newsrv->trackit = strdup(args[cur_arg + 1]);
4578
4579 cur_arg += 2;
4580 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004581 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 global.maxsock++;
4583 do_check = 1;
4584 cur_arg += 1;
4585 }
Willy Tarreau96839092010-03-29 10:02:24 +02004586 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4587 newsrv->state |= SRV_MAINTAIN;
4588 newsrv->state &= ~SRV_RUNNING;
4589 newsrv->health = 0;
4590 cur_arg += 1;
4591 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004592 else if (!strcmp(args[cur_arg], "ssl")) {
4593#ifdef USE_OPENSSL
4594 newsrv->use_ssl = 1;
4595 cur_arg += 1;
4596#else /* USE_OPENSSL */
4597 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4598 file, linenum, args[cur_arg]);
4599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
4601#endif /* USE_OPENSSL */
4602 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004603 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4604#ifdef USE_OPENSSL
4605 if (!*args[cur_arg + 1]) {
4606 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4607 file, linenum, args[0], args[cur_arg]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
4611
4612 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4613
4614 cur_arg += 2;
4615 continue;
4616#else
4617 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4618 file, linenum, args[0], args[cur_arg]);
4619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
4621#endif
4622 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004623 else if (!strcmp(args[cur_arg], "nosslv3")) {
4624#ifdef USE_OPENSSL
4625 newsrv->ssl_ctx.nosslv3 = 1;
4626 cur_arg += 1;
4627#else /* USE_OPENSSL */
4628 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4629 file, linenum, args[cur_arg]);
4630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
4632#endif /* USE_OPENSSL */
4633 }
4634 else if (!strcmp(args[cur_arg], "notlsv1")) {
4635#ifdef USE_OPENSSL
4636 newsrv->ssl_ctx.notlsv1 = 1;
4637 cur_arg += 1;
4638#else /* USE_OPENSSL */
4639 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4640 file, linenum, args[cur_arg]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643#endif /* USE_OPENSSL */
4644 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004645 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004646 if (!strcmp(args[cur_arg + 1], "none"))
4647 newsrv->observe = HANA_OBS_NONE;
4648 else if (!strcmp(args[cur_arg + 1], "layer4"))
4649 newsrv->observe = HANA_OBS_LAYER4;
4650 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4651 if (curproxy->mode != PR_MODE_HTTP) {
4652 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4653 file, linenum, args[cur_arg + 1]);
4654 err_code |= ERR_ALERT;
4655 }
4656 newsrv->observe = HANA_OBS_LAYER7;
4657 }
4658 else {
4659 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004660 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004661 file, linenum, args[cur_arg], args[cur_arg + 1]);
4662 err_code |= ERR_ALERT | ERR_FATAL;
4663 goto out;
4664 }
4665
4666 cur_arg += 2;
4667 }
4668 else if (!strcmp(args[cur_arg], "on-error")) {
4669 if (!strcmp(args[cur_arg + 1], "fastinter"))
4670 newsrv->onerror = HANA_ONERR_FASTINTER;
4671 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4672 newsrv->onerror = HANA_ONERR_FAILCHK;
4673 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4674 newsrv->onerror = HANA_ONERR_SUDDTH;
4675 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4676 newsrv->onerror = HANA_ONERR_MARKDWN;
4677 else {
4678 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004679 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004680 file, linenum, args[cur_arg], args[cur_arg + 1]);
4681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
4684
4685 cur_arg += 2;
4686 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004687 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4688 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4689 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4690 else {
4691 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4692 file, linenum, args[cur_arg], args[cur_arg + 1]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
4696
4697 cur_arg += 2;
4698 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004699 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4700 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4701 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4702 else {
4703 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4704 file, linenum, args[cur_arg], args[cur_arg + 1]);
4705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707 }
4708
4709 cur_arg += 2;
4710 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004711 else if (!strcmp(args[cur_arg], "error-limit")) {
4712 if (!*args[cur_arg + 1]) {
4713 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4714 file, linenum, args[cur_arg]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
4718
4719 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4720
4721 if (newsrv->consecutive_errors_limit <= 0) {
4722 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4723 file, linenum, args[cur_arg]);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004727 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004728 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004729 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004730 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004731 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004732
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004734#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004735 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004736 file, linenum, "source", "usesrc");
4737#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004738 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004740#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
4744 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004745 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4746 if (!sk) {
4747 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750 }
4751 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004752
4753 if (port_low != port_high) {
4754 int i;
4755 if (port_low <= 0 || port_low > 65535 ||
4756 port_high <= 0 || port_high > 65535 ||
4757 port_low > port_high) {
4758 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4759 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004762 }
4763 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4764 for (i = 0; i < newsrv->sport_range->size; i++)
4765 newsrv->sport_range->ports[i] = port_low + i;
4766 }
4767
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004769 while (*(args[cur_arg])) {
4770 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004771#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4772#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004773 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4774 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4775 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004778 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004779#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004780 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004781 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004782 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004785 }
4786 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004787 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004788 newsrv->state |= SRV_TPROXY_CLI;
4789 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004790 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004791 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004792 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4793 char *name, *end;
4794
4795 name = args[cur_arg+1] + 7;
4796 while (isspace(*name))
4797 name++;
4798
4799 end = name;
4800 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4801 end++;
4802
4803 newsrv->state &= ~SRV_TPROXY_MASK;
4804 newsrv->state |= SRV_TPROXY_DYN;
4805 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4806 newsrv->bind_hdr_len = end - name;
4807 memcpy(newsrv->bind_hdr_name, name, end - name);
4808 newsrv->bind_hdr_name[end-name] = '\0';
4809 newsrv->bind_hdr_occ = -1;
4810
4811 /* now look for an occurrence number */
4812 while (isspace(*end))
4813 end++;
4814 if (*end == ',') {
4815 end++;
4816 name = end;
4817 if (*end == '-')
4818 end++;
4819 while (isdigit(*end))
4820 end++;
4821 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4822 }
4823
4824 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4825 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4826 " occurrences values smaller than %d.\n",
4827 file, linenum, MAX_HDR_HISTORY);
4828 err_code |= ERR_ALERT | ERR_FATAL;
4829 goto out;
4830 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004831 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004832 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004833 if (!sk) {
4834 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
4838 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004839 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004840 }
4841 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004842#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004843 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004844#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004845 cur_arg += 2;
4846 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004847#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004848 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004849 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004850 err_code |= ERR_ALERT | ERR_FATAL;
4851 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004852#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4853 } /* "usesrc" */
4854
4855 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4856#ifdef SO_BINDTODEVICE
4857 if (!*args[cur_arg + 1]) {
4858 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4859 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004862 }
4863 if (newsrv->iface_name)
4864 free(newsrv->iface_name);
4865
4866 newsrv->iface_name = strdup(args[cur_arg + 1]);
4867 newsrv->iface_len = strlen(newsrv->iface_name);
4868 global.last_checks |= LSTCHK_NETADM;
4869#else
4870 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4871 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004874#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004875 cur_arg += 2;
4876 continue;
4877 }
4878 /* this keyword in not an option of "source" */
4879 break;
4880 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004882 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004883 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4884 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004889 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004890 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004891 file, linenum, newsrv->id);
4892 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004893 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004894 file, linenum);
4895
Willy Tarreau93893792009-07-23 13:19:11 +02004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899 }
4900
4901 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004902 if (newsrv->trackit) {
4903 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4904 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004907 }
4908
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004909 /* try to get the port from check_addr if check_port not set */
4910 if (!newsrv->check_port)
4911 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004912
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4914 newsrv->check_port = realport; /* by default */
4915 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004916 /* not yet valid, because no port was set on
4917 * the server either. We'll check if we have
4918 * a known port on the first listener.
4919 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004920 struct listener *l = curproxy->listen;
4921 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4922 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004923 }
4924 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4926 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004930
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004931 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004932 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004933 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4934 err_code |= ERR_ALERT | ERR_ABORT;
4935 goto out;
4936 }
4937
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004938 /* Allocate buffer for partial check results... */
4939 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4940 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4941 err_code |= ERR_ALERT | ERR_ABORT;
4942 goto out;
4943 }
4944
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004945 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 newsrv->state |= SRV_CHECKED;
4947 }
4948
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004949 if (!defsrv) {
4950 if (newsrv->state & SRV_BACKUP)
4951 curproxy->srv_bck++;
4952 else
4953 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004954
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004955 newsrv->prev_state = newsrv->state;
4956 }
William Lallemanda73203e2012-03-12 12:48:57 +01004957 }
4958
4959 else if (strcmp(args[0], "unique-id-format") == 0) {
4960 if (!*(args[1])) {
4961 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
4964 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004965 free(curproxy->uniqueid_format_string);
4966 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004967 }
William Lallemanda73203e2012-03-12 12:48:57 +01004968
4969 else if (strcmp(args[0], "unique-id-header") == 0) {
4970 if (!*(args[1])) {
4971 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975 free(curproxy->header_unique_id);
4976 curproxy->header_unique_id = strdup(args[1]);
4977 }
4978
William Lallemand723b73a2012-02-08 16:37:49 +01004979 else if (strcmp(args[0], "log-format") == 0) {
4980 if (!*(args[1])) {
4981 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4982 err_code |= ERR_ALERT | ERR_FATAL;
4983 goto out;
4984 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004985
4986 if (curproxy->logformat_string != default_http_log_format &&
4987 curproxy->logformat_string != default_tcp_log_format &&
4988 curproxy->logformat_string != clf_http_log_format)
4989 free(curproxy->logformat_string);
4990 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 }
William Lallemand723b73a2012-02-08 16:37:49 +01004992
William Lallemand0f99e342011-10-12 17:50:54 +02004993 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4994 /* delete previous herited or defined syslog servers */
4995 struct logsrv *back;
4996
4997 if (*(args[1]) != 0) {
4998 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
5001 }
5002
William Lallemand723b73a2012-02-08 16:37:49 +01005003 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5004 LIST_DEL(&tmplogsrv->list);
5005 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005006 }
5007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005009 struct logsrv *logsrv;
5010
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005012 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005013 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005014 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005015 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005016 LIST_INIT(&node->list);
5017 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
5020 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005021
5022 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023
William Lallemand0f99e342011-10-12 17:50:54 +02005024 logsrv->facility = get_log_facility(args[2]);
5025 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031
William Lallemand0f99e342011-10-12 17:50:54 +02005032 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005034 logsrv->level = get_log_level(args[3]);
5035 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
5041 }
5042
William Lallemand0f99e342011-10-12 17:50:54 +02005043 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005044 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005045 logsrv->minlvl = get_log_level(args[4]);
5046 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005047 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
5050
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005051 }
5052 }
5053
Robert Tsai81ae1952007-12-05 10:47:29 +01005054 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01005055 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005056 if (!sk) {
5057 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01005058 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
5061 }
William Lallemand0f99e342011-10-12 17:50:54 +02005062 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01005063 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005064 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01005065 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01005066 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
5069 }
William Lallemand0f99e342011-10-12 17:50:54 +02005070 logsrv->addr = *sk;
5071 if (!get_host_port(&logsrv->addr))
5072 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 }
William Lallemand0f99e342011-10-12 17:50:54 +02005074
5075 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
5077 else {
5078 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5079 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 }
5084 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005085 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005086 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005087
Willy Tarreau977b8e42006-12-29 14:19:17 +01005088 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005089 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005090
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5093 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005097
5098 /* we must first clear any optional default setting */
5099 curproxy->options &= ~PR_O_TPXY_MASK;
5100 free(curproxy->iface_name);
5101 curproxy->iface_name = NULL;
5102 curproxy->iface_len = 0;
5103
Willy Tarreaud5191e72010-02-09 20:50:45 +01005104 sk = str2sa(args[1]);
5105 if (!sk) {
5106 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005112
5113 cur_arg = 2;
5114 while (*(args[cur_arg])) {
5115 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005116#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
5117#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
5119 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5120 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005123 }
5124#endif
5125 if (!*args[cur_arg + 1]) {
5126 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5127 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005130 }
5131
5132 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005133 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005134 curproxy->options |= PR_O_TPXY_CLI;
5135 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005136 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005138 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5139 char *name, *end;
5140
5141 name = args[cur_arg+1] + 7;
5142 while (isspace(*name))
5143 name++;
5144
5145 end = name;
5146 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5147 end++;
5148
5149 curproxy->options &= ~PR_O_TPXY_MASK;
5150 curproxy->options |= PR_O_TPXY_DYN;
5151 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5152 curproxy->bind_hdr_len = end - name;
5153 memcpy(curproxy->bind_hdr_name, name, end - name);
5154 curproxy->bind_hdr_name[end-name] = '\0';
5155 curproxy->bind_hdr_occ = -1;
5156
5157 /* now look for an occurrence number */
5158 while (isspace(*end))
5159 end++;
5160 if (*end == ',') {
5161 end++;
5162 name = end;
5163 if (*end == '-')
5164 end++;
5165 while (isdigit(*end))
5166 end++;
5167 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5168 }
5169
5170 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5171 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5172 " occurrences values smaller than %d.\n",
5173 file, linenum, MAX_HDR_HISTORY);
5174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
5176 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005177 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005178 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005179 if (!sk) {
5180 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5181 err_code |= ERR_ALERT | ERR_FATAL;
5182 goto out;
5183 }
5184 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005185 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005186 }
5187 global.last_checks |= LSTCHK_NETADM;
5188#if !defined(CONFIG_HAP_LINUX_TPROXY)
5189 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005190#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005191#else /* no TPROXY support */
5192 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005193 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005196#endif
5197 cur_arg += 2;
5198 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005199 }
5200
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005201 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5202#ifdef SO_BINDTODEVICE
5203 if (!*args[cur_arg + 1]) {
5204 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5205 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005208 }
5209 if (curproxy->iface_name)
5210 free(curproxy->iface_name);
5211
5212 curproxy->iface_name = strdup(args[cur_arg + 1]);
5213 curproxy->iface_len = strlen(curproxy->iface_name);
5214 global.last_checks |= LSTCHK_NETADM;
5215#else
5216 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5217 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005220#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005221 cur_arg += 2;
5222 continue;
5223 }
5224 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5225 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005230 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5231 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5232 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5239 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243
5244 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005245 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005246 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
5250 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005251 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005252 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005253 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
5257 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005259 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005260 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
5264 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005265 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005266 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005267 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 }
5271 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005273 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005274 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005278 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005280 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005281 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005283 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005284 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005285 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005286 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005287 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005288 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005290 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005291 }
5292 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005293 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005294 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005295 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005297 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005298 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005300 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306
5307 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005308 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005309 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005314 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005315 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005316 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005318 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 }
5320 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005321 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005322 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005323 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005324 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
5327 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005328 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005329 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005330 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005331 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 }
5334 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005335 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005336 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005337 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005338 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005341 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005342 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005343 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005344 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005345 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005346 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005349 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005350
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 if (curproxy == &defproxy) {
5352 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005356 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005357 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 if (*(args[1]) == 0) {
5360 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005364
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005365 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005366 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5367 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5368 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5373 }
5374 else if (*args[2]) {
5375 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5376 file, linenum, args[0], args[2]);
5377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 }
5380
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005381 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005382 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005383 wl->s = strdup(args[1]);
5384 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005385 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 }
5387 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005388 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5390 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005394
Willy Tarreauade5ec42010-01-28 19:33:49 +01005395 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005396 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005397 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005398 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 }
5401 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005402 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005403 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005404 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005405 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 }
5408 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005409 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005410 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005411 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005412 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414 }
5415 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005416 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 }
5422
Willy Tarreauade5ec42010-01-28 19:33:49 +01005423 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005424 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005425 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005426 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 }
5429 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005430 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005431 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005432 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005433 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 }
5436 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005437 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005438 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005439 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005440 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005444 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005445
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 if (curproxy == &defproxy) {
5447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005451 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005452 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 if (*(args[1]) == 0) {
5455 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005458 }
5459
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005460 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005461 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5462 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5463 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 }
5467 err_code |= warnif_cond_requires_req(cond, file, linenum);
5468 }
5469 else if (*args[2]) {
5470 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5471 file, linenum, args[0], args[2]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005476 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005477 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005478 wl->s = strdup(args[1]);
5479 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 }
5481 else if (!strcmp(args[0], "errorloc") ||
5482 !strcmp(args[0], "errorloc302") ||
5483 !strcmp(args[0], "errorloc303")) { /* error location */
5484 int errnum, errlen;
5485 char *err;
5486
Willy Tarreau977b8e42006-12-29 14:19:17 +01005487 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005489
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005491 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
5493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 }
5495
5496 errnum = atol(args[1]);
5497 if (!strcmp(args[0], "errorloc303")) {
5498 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5499 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5500 } else {
5501 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5502 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5503 }
5504
Willy Tarreau0f772532006-12-23 20:51:41 +01005505 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5506 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005507 chunk_destroy(&curproxy->errmsg[rc]);
5508 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005509 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005512
5513 if (rc >= HTTP_ERR_SIZE) {
5514 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5515 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 free(err);
5517 }
5518 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005519 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5520 int errnum, errlen, fd;
5521 char *err;
5522 struct stat stat;
5523
5524 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005526
5527 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005528 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005531 }
5532
5533 fd = open(args[2], O_RDONLY);
5534 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5535 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5536 file, linenum, args[2], args[1]);
5537 if (fd >= 0)
5538 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005541 }
5542
Willy Tarreau27a674e2009-08-17 07:23:33 +02005543 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005544 errlen = stat.st_size;
5545 } else {
5546 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005547 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005548 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005549 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005550 }
5551
5552 err = malloc(errlen); /* malloc() must succeed during parsing */
5553 errnum = read(fd, err, errlen);
5554 if (errnum != errlen) {
5555 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5556 file, linenum, args[2], args[1]);
5557 close(fd);
5558 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005561 }
5562 close(fd);
5563
5564 errnum = atol(args[1]);
5565 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5566 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005567 chunk_destroy(&curproxy->errmsg[rc]);
5568 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005569 break;
5570 }
5571 }
5572
5573 if (rc >= HTTP_ERR_SIZE) {
5574 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5575 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005576 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005577 free(err);
5578 }
5579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005581 struct cfg_kw_list *kwl;
5582 int index;
5583
5584 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5585 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5586 if (kwl->kw[index].section != CFG_LISTEN)
5587 continue;
5588 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5589 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005590 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005591 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005592 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005593 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005594 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005597 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005598 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005599 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_WARN;
5601 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005602 }
Willy Tarreau93893792009-07-23 13:19:11 +02005603 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005604 }
5605 }
5606 }
5607
Willy Tarreau6daf3432008-01-22 16:44:08 +01005608 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 }
Willy Tarreau93893792009-07-23 13:19:11 +02005612 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005613 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005614 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615}
5616
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005617int
5618cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5619{
5620
5621 int err_code = 0;
5622 const char *err;
5623
5624 if (!strcmp(args[0], "userlist")) { /* new userlist */
5625 struct userlist *newul;
5626
5627 if (!*args[1]) {
5628 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5629 file, linenum, args[0]);
5630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632 }
5633
5634 err = invalid_char(args[1]);
5635 if (err) {
5636 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5637 file, linenum, *err, args[0], args[1]);
5638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
5640 }
5641
5642 for (newul = userlist; newul; newul = newul->next)
5643 if (!strcmp(newul->name, args[1])) {
5644 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5645 file, linenum, args[1]);
5646 err_code |= ERR_WARN;
5647 goto out;
5648 }
5649
5650 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5651 if (!newul) {
5652 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5653 err_code |= ERR_ALERT | ERR_ABORT;
5654 goto out;
5655 }
5656
5657 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5658 newul->name = strdup(args[1]);
5659
5660 if (!newul->groupusers | !newul->name) {
5661 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5662 err_code |= ERR_ALERT | ERR_ABORT;
5663 goto out;
5664 }
5665
5666 newul->next = userlist;
5667 userlist = newul;
5668
5669 } else if (!strcmp(args[0], "group")) { /* new group */
5670 int cur_arg, i;
5671 const char *err;
5672
5673 if (!*args[1]) {
5674 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5675 file, linenum, args[0]);
5676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
5678 }
5679
5680 err = invalid_char(args[1]);
5681 if (err) {
5682 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5683 file, linenum, *err, args[0], args[1]);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
5687
5688 for(i = 0; i < userlist->grpcnt; i++)
5689 if (!strcmp(userlist->groups[i], args[1])) {
5690 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5691 file, linenum, args[1], userlist->name);
5692 err_code |= ERR_ALERT;
5693 goto out;
5694 }
5695
5696 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5697 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5698 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701 }
5702
5703 cur_arg = 2;
5704
5705 while (*args[cur_arg]) {
5706 if (!strcmp(args[cur_arg], "users")) {
5707 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5708 cur_arg += 2;
5709 continue;
5710 } else {
5711 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5712 file, linenum, args[0]);
5713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
5715 }
5716 }
5717
5718 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5719 } else if (!strcmp(args[0], "user")) { /* new user */
5720 struct auth_users *newuser;
5721 int cur_arg;
5722
5723 if (!*args[1]) {
5724 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5725 file, linenum, args[0]);
5726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
5728 }
5729
5730 for (newuser = userlist->users; newuser; newuser = newuser->next)
5731 if (!strcmp(newuser->user, args[1])) {
5732 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5733 file, linenum, args[1], userlist->name);
5734 err_code |= ERR_ALERT;
5735 goto out;
5736 }
5737
5738 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5739 if (!newuser) {
5740 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5741 err_code |= ERR_ALERT | ERR_ABORT;
5742 goto out;
5743 }
5744
5745 newuser->user = strdup(args[1]);
5746
5747 newuser->next = userlist->users;
5748 userlist->users = newuser;
5749
5750 cur_arg = 2;
5751
5752 while (*args[cur_arg]) {
5753 if (!strcmp(args[cur_arg], "password")) {
5754#ifndef CONFIG_HAP_CRYPT
5755 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5756 file, linenum);
5757 err_code |= ERR_ALERT;
5758#endif
5759 newuser->pass = strdup(args[cur_arg + 1]);
5760 cur_arg += 2;
5761 continue;
5762 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5763 newuser->pass = strdup(args[cur_arg + 1]);
5764 newuser->flags |= AU_O_INSECURE;
5765 cur_arg += 2;
5766 continue;
5767 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005768 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005769 cur_arg += 2;
5770 continue;
5771 } else {
5772 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5773 file, linenum, args[0]);
5774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
5776 }
5777 }
5778 } else {
5779 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5780 err_code |= ERR_ALERT | ERR_FATAL;
5781 }
5782
5783out:
5784 return err_code;
5785}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786
5787/*
5788 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005789 * Returns the error code, 0 if OK, or any combination of :
5790 * - ERR_ABORT: must abort ASAP
5791 * - ERR_FATAL: we can continue parsing but not start the service
5792 * - ERR_WARN: a warning has been emitted
5793 * - ERR_ALERT: an alert has been emitted
5794 * Only the two first ones can stop processing, the two others are just
5795 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005797int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005799 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005800 FILE *f;
5801 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005803 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005804
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 if ((f=fopen(file,"r")) == NULL)
5806 return -1;
5807
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005808 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005809 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005810 char *end;
5811 char *args[MAX_LINE_ARGS + 1];
5812 char *line = thisline;
5813
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 linenum++;
5815
5816 end = line + strlen(line);
5817
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005818 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5819 /* Check if we reached the limit and the last char is not \n.
5820 * Watch out for the last line without the terminating '\n'!
5821 */
5822 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005823 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005824 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005825 }
5826
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005828 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 line++;
5830
5831 arg = 0;
5832 args[arg] = line;
5833
5834 while (*line && arg < MAX_LINE_ARGS) {
5835 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5836 * C equivalent value. Other combinations left unchanged (eg: \1).
5837 */
5838 if (*line == '\\') {
5839 int skip = 0;
5840 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5841 *line = line[1];
5842 skip = 1;
5843 }
5844 else if (line[1] == 'r') {
5845 *line = '\r';
5846 skip = 1;
5847 }
5848 else if (line[1] == 'n') {
5849 *line = '\n';
5850 skip = 1;
5851 }
5852 else if (line[1] == 't') {
5853 *line = '\t';
5854 skip = 1;
5855 }
5856 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005857 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005858 unsigned char hex1, hex2;
5859 hex1 = toupper(line[2]) - '0';
5860 hex2 = toupper(line[3]) - '0';
5861 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5862 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5863 *line = (hex1<<4) + hex2;
5864 skip = 3;
5865 }
5866 else {
5867 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 }
5870 }
5871 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005872 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 end -= skip;
5874 }
5875 line++;
5876 }
5877 else if (*line == '#' || *line == '\n' || *line == '\r') {
5878 /* end of string, end of loop */
5879 *line = 0;
5880 break;
5881 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005882 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005884 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005885 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 line++;
5887 args[++arg] = line;
5888 }
5889 else {
5890 line++;
5891 }
5892 }
5893
5894 /* empty line */
5895 if (!**args)
5896 continue;
5897
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005898 if (*line) {
5899 /* we had to stop due to too many args.
5900 * Let's terminate the string, print the offending part then cut the
5901 * last arg.
5902 */
5903 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5904 line++;
5905 *line = '\0';
5906
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005907 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005908 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005909 err_code |= ERR_ALERT | ERR_FATAL;
5910 args[arg] = line;
5911 }
5912
Willy Tarreau540abe42007-05-02 20:50:16 +02005913 /* zero out remaining args and ensure that at least one entry
5914 * is zeroed out.
5915 */
5916 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 args[arg] = line;
5918 }
5919
Willy Tarreau3842f002009-06-14 11:39:52 +02005920 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005921 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005922 char *tmp;
5923
Willy Tarreau3842f002009-06-14 11:39:52 +02005924 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005925 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005926 for (arg=0; *args[arg+1]; arg++)
5927 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005928 *tmp = '\0'; // fix the next arg to \0
5929 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005930 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005931 else if (!strcmp(args[0], "default")) {
5932 kwm = KWM_DEF;
5933 for (arg=0; *args[arg+1]; arg++)
5934 args[arg] = args[arg+1]; // shift args after inversion
5935 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005936
William Lallemand0f99e342011-10-12 17:50:54 +02005937 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5938 strcmp(args[0], "log") != 0) {
5939 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005940 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005941 }
5942
Willy Tarreau977b8e42006-12-29 14:19:17 +01005943 if (!strcmp(args[0], "listen") ||
5944 !strcmp(args[0], "frontend") ||
5945 !strcmp(args[0], "backend") ||
5946 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005947 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005949 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005950 cursection = strdup(args[0]);
5951 }
5952 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005953 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005954 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005955 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005956 }
5957 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005958 confsect = CFG_USERLIST;
5959 free(cursection);
5960 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005961 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005962 else if (!strcmp(args[0], "peers")) {
5963 confsect = CFG_PEERS;
5964 free(cursection);
5965 cursection = strdup(args[0]);
5966 }
5967
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 /* else it's a section keyword */
5969
5970 switch (confsect) {
5971 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005972 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 break;
5974 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005975 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005977 case CFG_USERLIST:
5978 err_code |= cfg_parse_users(file, linenum, args, kwm);
5979 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005980 case CFG_PEERS:
5981 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5982 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005984 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005985 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005986 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005987
5988 if (err_code & ERR_ABORT)
5989 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005990 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005991 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005992 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005993 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005994 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005995}
5996
Willy Tarreaubb925012009-07-23 13:36:36 +02005997/*
5998 * Returns the error code, 0 if OK, or any combination of :
5999 * - ERR_ABORT: must abort ASAP
6000 * - ERR_FATAL: we can continue parsing but not start the service
6001 * - ERR_WARN: a warning has been emitted
6002 * - ERR_ALERT: an alert has been emitted
6003 * Only the two first ones can stop processing, the two others are just
6004 * indicators.
6005 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006006int check_config_validity()
6007{
6008 int cfgerr = 0;
6009 struct proxy *curproxy = NULL;
6010 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006011 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006012 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006013 unsigned int next_pxid = 1;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006014 struct ssl_conf *ssl_conf, *ssl_back;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006016 ssl_back = ssl_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 /*
6018 * Now, check for the integrity of all that we have collected.
6019 */
6020
6021 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006022 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006024 /* first, we will invert the proxy list order */
6025 curproxy = NULL;
6026 while (proxy) {
6027 struct proxy *next;
6028
6029 next = proxy->next;
6030 proxy->next = curproxy;
6031 curproxy = proxy;
6032 if (!next)
6033 break;
6034 proxy = next;
6035 }
6036
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006038 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006039 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006040 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006041 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006042 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006043 unsigned int next_id;
6044
6045 if (!curproxy->uuid) {
6046 /* proxy ID not set, use automatic numbering with first
6047 * spare entry starting with next_pxid.
6048 */
6049 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6050 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6051 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006052 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006053 next_pxid++;
6054
Willy Tarreau55ea7572007-06-17 19:56:27 +02006055
Willy Tarreaubaaee002006-06-26 02:48:02 +02006056 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006057 /* ensure we don't keep listeners uselessly bound */
6058 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006059 curproxy = curproxy->next;
6060 continue;
6061 }
6062
Willy Tarreauff01a212009-03-15 13:46:16 +01006063 switch (curproxy->mode) {
6064 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006065 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006066 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006067 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6068 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006069 cfgerr++;
6070 }
6071
6072 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006073 Warning("config : servers will be ignored for %s '%s'.\n",
6074 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006075 break;
6076
6077 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006078 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006079 break;
6080
6081 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006082 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006083 break;
6084 }
6085
6086 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006087 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
6088 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089 cfgerr++;
6090 }
Willy Tarreauff01a212009-03-15 13:46:16 +01006091
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006092 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006093 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006094 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006095 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6096 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006097 cfgerr++;
6098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006099#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006100 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006101 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6102 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006103 cfgerr++;
6104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006106 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006107 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6108 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006109 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006110 }
6111 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006112 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006113 /* If no LB algo is set in a backend, and we're not in
6114 * transparent mode, dispatch mode nor proxy mode, we
6115 * want to use balance roundrobin by default.
6116 */
6117 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6118 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006119 }
6120 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006121
Willy Tarreau1620ec32011-08-06 17:05:02 +02006122 if (curproxy->options & PR_O_DISPATCH)
6123 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6124 else if (curproxy->options & PR_O_HTTP_PROXY)
6125 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6126 else if (curproxy->options & PR_O_TRANSP)
6127 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006128
Willy Tarreau1620ec32011-08-06 17:05:02 +02006129 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6130 if (curproxy->options & PR_O_DISABLE404) {
6131 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6132 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6133 err_code |= ERR_WARN;
6134 curproxy->options &= ~PR_O_DISABLE404;
6135 }
6136 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6137 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6138 "send-state", proxy_type_str(curproxy), curproxy->id);
6139 err_code |= ERR_WARN;
6140 curproxy->options &= ~PR_O2_CHK_SNDST;
6141 }
Willy Tarreauef781042010-01-27 11:53:01 +01006142 }
6143
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006144 /* if a default backend was specified, let's find it */
6145 if (curproxy->defbe.name) {
6146 struct proxy *target;
6147
Alex Williams96532db2009-11-01 21:27:13 -05006148 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006149 if (!target) {
6150 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6151 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006152 cfgerr++;
6153 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006154 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6155 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006156 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006157 } else {
6158 free(curproxy->defbe.name);
6159 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006160 /* we force the backend to be present on at least all of
6161 * the frontend's processes.
6162 */
6163 target->bind_proc = curproxy->bind_proc ?
6164 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006165
6166 /* Emit a warning if this proxy also has some servers */
6167 if (curproxy->srv) {
6168 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6169 curproxy->id);
6170 err_code |= ERR_WARN;
6171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
6173 }
6174
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006175 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006176 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6177 /* map jump target for ACT_SETBE in req_rep chain */
6178 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006179 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006180 struct proxy *target;
6181
Willy Tarreaua496b602006-12-17 23:15:24 +01006182 if (exp->action != ACT_SETBE)
6183 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006184
Alex Williams96532db2009-11-01 21:27:13 -05006185 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006186 if (!target) {
6187 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6188 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006189 cfgerr++;
6190 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006191 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6192 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006193 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006194 } else {
6195 free((void *)exp->replace);
6196 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006197 /* we force the backend to be present on at least all of
6198 * the frontend's processes.
6199 */
6200 target->bind_proc = curproxy->bind_proc ?
6201 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006202 }
6203 }
6204 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006205
6206 /* find the target proxy for 'use_backend' rules */
6207 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006208 struct proxy *target;
6209
Alex Williams96532db2009-11-01 21:27:13 -05006210 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006211
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006212 if (!target) {
6213 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6214 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006215 cfgerr++;
6216 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006217 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6218 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006219 cfgerr++;
6220 } else {
6221 free((void *)rule->be.name);
6222 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006223 /* we force the backend to be present on at least all of
6224 * the frontend's processes.
6225 */
6226 target->bind_proc = curproxy->bind_proc ?
6227 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006228 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006229 }
6230
6231 /* find the target proxy for 'use_backend' rules */
6232 list_for_each_entry(srule, &curproxy->server_rules, list) {
6233 struct server *target = findserver(curproxy, srule->srv.name);
6234
6235 if (!target) {
6236 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6237 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6238 cfgerr++;
6239 continue;
6240 }
6241 free((void *)srule->srv.name);
6242 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006243 }
6244
Emeric Brunb982a3d2010-01-04 15:45:53 +01006245 /* find the target table for 'stick' rules */
6246 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6247 struct proxy *target;
6248
Emeric Brun1d33b292010-01-04 15:47:17 +01006249 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6250 if (mrule->flags & STK_IS_STORE)
6251 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6252
Emeric Brunb982a3d2010-01-04 15:45:53 +01006253 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006254 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006255 else
6256 target = curproxy;
6257
6258 if (!target) {
6259 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6260 curproxy->id, mrule->table.name);
6261 cfgerr++;
6262 }
6263 else if (target->table.size == 0) {
6264 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6265 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6266 cfgerr++;
6267 }
Willy Tarreau12785782012-04-27 21:37:17 +02006268 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6269 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006270 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6271 cfgerr++;
6272 }
6273 else {
6274 free((void *)mrule->table.name);
6275 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006276 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006277 }
6278 }
6279
6280 /* find the target table for 'store response' rules */
6281 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6282 struct proxy *target;
6283
Emeric Brun1d33b292010-01-04 15:47:17 +01006284 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6285
Emeric Brunb982a3d2010-01-04 15:45:53 +01006286 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006287 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006288 else
6289 target = curproxy;
6290
6291 if (!target) {
6292 Alert("Proxy '%s': unable to find store table '%s'.\n",
6293 curproxy->id, mrule->table.name);
6294 cfgerr++;
6295 }
6296 else if (target->table.size == 0) {
6297 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6298 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6299 cfgerr++;
6300 }
Willy Tarreau12785782012-04-27 21:37:17 +02006301 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6302 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006303 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6304 cfgerr++;
6305 }
6306 else {
6307 free((void *)mrule->table.name);
6308 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006309 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006310 }
6311 }
6312
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006313 /* find the target table for 'tcp-request' layer 4 rules */
6314 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6315 struct proxy *target;
6316
Willy Tarreau56123282010-08-06 19:06:56 +02006317 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006318 continue;
6319
6320 if (trule->act_prm.trk_ctr.table.n)
6321 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6322 else
6323 target = curproxy;
6324
6325 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006326 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6327 curproxy->id, trule->act_prm.trk_ctr.table.n,
6328 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006329 cfgerr++;
6330 }
6331 else if (target->table.size == 0) {
6332 Alert("Proxy '%s': table '%s' used but not configured.\n",
6333 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6334 cfgerr++;
6335 }
6336 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006337 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 +02006338 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6339 cfgerr++;
6340 }
6341 else {
6342 free(trule->act_prm.trk_ctr.table.n);
6343 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006344 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006345 * to pass a list of counters to track and allocate them right here using
6346 * stktable_alloc_data_type().
6347 */
6348 }
6349 }
6350
Willy Tarreaud1f96522010-08-03 19:34:32 +02006351 /* find the target table for 'tcp-request' layer 6 rules */
6352 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6353 struct proxy *target;
6354
Willy Tarreau56123282010-08-06 19:06:56 +02006355 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006356 continue;
6357
6358 if (trule->act_prm.trk_ctr.table.n)
6359 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6360 else
6361 target = curproxy;
6362
6363 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006364 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6365 curproxy->id, trule->act_prm.trk_ctr.table.n,
6366 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006367 cfgerr++;
6368 }
6369 else if (target->table.size == 0) {
6370 Alert("Proxy '%s': table '%s' used but not configured.\n",
6371 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6372 cfgerr++;
6373 }
6374 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006375 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 +02006376 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6377 cfgerr++;
6378 }
6379 else {
6380 free(trule->act_prm.trk_ctr.table.n);
6381 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006382 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006383 * to pass a list of counters to track and allocate them right here using
6384 * stktable_alloc_data_type().
6385 */
6386 }
6387 }
6388
Emeric Brun32da3c42010-09-23 18:39:19 +02006389 if (curproxy->table.peers.name) {
6390 struct peers *curpeers = peers;
6391
6392 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6393 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6394 free((void *)curproxy->table.peers.name);
6395 curproxy->table.peers.p = peers;
6396 break;
6397 }
6398 }
6399
6400 if (!curpeers) {
6401 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6402 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006403 free((void *)curproxy->table.peers.name);
6404 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006405 cfgerr++;
6406 }
6407 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006408 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6409 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006410 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006411 cfgerr++;
6412 }
6413 }
6414
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006415 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006416 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006417 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6418 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6419 "proxy", curproxy->id);
6420 cfgerr++;
6421 goto out_uri_auth_compat;
6422 }
6423
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006424 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006425 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006426 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006427 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006428
Willy Tarreau95fa4692010-02-01 13:05:50 +01006429 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6430 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006431
6432 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006433 uri_auth_compat_req[i++] = "realm";
6434 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6435 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006436
Willy Tarreau95fa4692010-02-01 13:05:50 +01006437 uri_auth_compat_req[i++] = "unless";
6438 uri_auth_compat_req[i++] = "{";
6439 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6440 uri_auth_compat_req[i++] = "}";
6441 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006442
Willy Tarreauff011f22011-01-06 17:51:27 +01006443 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6444 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006445 cfgerr++;
6446 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006447 }
6448
Willy Tarreauff011f22011-01-06 17:51:27 +01006449 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006450
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006451 if (curproxy->uri_auth->auth_realm) {
6452 free(curproxy->uri_auth->auth_realm);
6453 curproxy->uri_auth->auth_realm = NULL;
6454 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006455
6456 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006457 }
6458out_uri_auth_compat:
6459
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006460 cfgerr += acl_find_targets(curproxy);
6461
Willy Tarreau2738a142006-07-08 17:28:09 +02006462 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006463 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006464 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006465 (!curproxy->timeout.connect ||
6466 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006467 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006468 " | While not properly invalid, you will certainly encounter various problems\n"
6469 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006470 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006471 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006472 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006473 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006474
Willy Tarreau1fa31262007-12-03 00:36:16 +01006475 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6476 * We must still support older configurations, so let's find out whether those
6477 * parameters have been set or must be copied from contimeouts.
6478 */
6479 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006480 if (!curproxy->timeout.tarpit ||
6481 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006482 /* tarpit timeout not set. We search in the following order:
6483 * default.tarpit, curr.connect, default.connect.
6484 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006485 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006486 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006487 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006488 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006489 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006490 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006491 }
6492 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006493 (!curproxy->timeout.queue ||
6494 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006495 /* queue timeout not set. We search in the following order:
6496 * default.queue, curr.connect, default.connect.
6497 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006498 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006499 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006500 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006501 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006502 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006503 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006504 }
6505 }
6506
Willy Tarreau1620ec32011-08-06 17:05:02 +02006507 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006508 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6509 curproxy->check_req = (char *)malloc(curproxy->check_len);
6510 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006511 }
6512
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006513 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006514 if (curproxy->nb_req_cap) {
6515 if (curproxy->mode == PR_MODE_HTTP) {
6516 curproxy->req_cap_pool = create_pool("ptrcap",
6517 curproxy->nb_req_cap * sizeof(char *),
6518 MEM_F_SHARED);
6519 } else {
6520 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6521 proxy_type_str(curproxy), curproxy->id);
6522 err_code |= ERR_WARN;
6523 curproxy->to_log &= ~LW_REQHDR;
6524 curproxy->nb_req_cap = 0;
6525 }
6526 }
6527
6528 if (curproxy->nb_rsp_cap) {
6529 if (curproxy->mode == PR_MODE_HTTP) {
6530 curproxy->rsp_cap_pool = create_pool("ptrcap",
6531 curproxy->nb_rsp_cap * sizeof(char *),
6532 MEM_F_SHARED);
6533 } else {
6534 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6535 proxy_type_str(curproxy), curproxy->id);
6536 err_code |= ERR_WARN;
6537 curproxy->to_log &= ~LW_REQHDR;
6538 curproxy->nb_rsp_cap = 0;
6539 }
6540 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006541
Willy Tarreau196729e2012-05-31 19:30:26 +02006542 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006543 if (!(curproxy->cap & PR_CAP_FE)) {
6544 if (curproxy->logformat_string != default_http_log_format &&
6545 curproxy->logformat_string != default_tcp_log_format &&
6546 curproxy->logformat_string != clf_http_log_format)
6547 free(curproxy->logformat_string);
6548 curproxy->logformat_string = NULL;
6549 }
6550
Willy Tarreau196729e2012-05-31 19:30:26 +02006551 if (curproxy->logformat_string)
6552 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6553
6554 if (curproxy->uniqueid_format_string)
6555 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6556
Willy Tarreaubaaee002006-06-26 02:48:02 +02006557 /* first, we will invert the servers list order */
6558 newsrv = NULL;
6559 while (curproxy->srv) {
6560 struct server *next;
6561
6562 next = curproxy->srv->next;
6563 curproxy->srv->next = newsrv;
6564 newsrv = curproxy->srv;
6565 if (!next)
6566 break;
6567 curproxy->srv = next;
6568 }
6569
Willy Tarreaudd701652010-05-25 23:03:02 +02006570 /* assign automatic UIDs to servers which don't have one yet */
6571 next_id = 1;
6572 newsrv = curproxy->srv;
6573 while (newsrv != NULL) {
6574 if (!newsrv->puid) {
6575 /* server ID not set, use automatic numbering with first
6576 * spare entry starting with next_svid.
6577 */
6578 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6579 newsrv->conf.id.key = newsrv->puid = next_id;
6580 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6581 }
6582 next_id++;
6583 newsrv = newsrv->next;
6584 }
6585
Willy Tarreau20697042007-11-15 23:26:18 +01006586 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006587 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588
Willy Tarreau62c3be22012-01-20 13:12:32 +01006589 /*
6590 * If this server supports a maxconn parameter, it needs a dedicated
6591 * tasks to fill the emptied slots when a connection leaves.
6592 * Also, resolve deferred tracking dependency if needed.
6593 */
6594 newsrv = curproxy->srv;
6595 while (newsrv != NULL) {
6596 if (newsrv->minconn > newsrv->maxconn) {
6597 /* Only 'minconn' was specified, or it was higher than or equal
6598 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6599 * this will avoid further useless expensive computations.
6600 */
6601 newsrv->maxconn = newsrv->minconn;
6602 } else if (newsrv->maxconn && !newsrv->minconn) {
6603 /* minconn was not specified, so we set it to maxconn */
6604 newsrv->minconn = newsrv->maxconn;
6605 }
6606
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006607#ifdef USE_OPENSSL
6608#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6609#define SSL_OP_NO_COMPRESSION 0
6610#endif
6611#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6612#define SSL_MODE_RELEASE_BUFFERS 0
6613#endif
6614#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6615#define SSL_OP_NO_COMPRESSION 0
6616#endif
6617 if (newsrv->use_ssl) {
6618 int ssloptions =
6619 SSL_OP_ALL | /* all known workarounds for bugs */
6620 SSL_OP_NO_SSLv2 |
6621 SSL_OP_NO_COMPRESSION;
6622 int sslmode =
6623 SSL_MODE_ENABLE_PARTIAL_WRITE |
6624 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6625 SSL_MODE_RELEASE_BUFFERS;
6626
6627 /* Initiate SSL context for current server */
6628 newsrv->ssl_ctx.reused_sess = NULL;
6629 newsrv->data = &ssl_sock;
6630 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6631 if(!newsrv->ssl_ctx.ctx) {
6632
6633 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6634 proxy_type_str(curproxy), curproxy->id,
6635 newsrv->id);
6636 cfgerr++;
6637 goto next_srv;
6638 }
6639
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006640 if (newsrv->ssl_ctx.nosslv3)
6641 ssloptions |= SSL_OP_NO_SSLv3;
6642 if (newsrv->ssl_ctx.notlsv1)
6643 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006644 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6645 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6646 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6647 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006648 if (newsrv->ssl_ctx.ciphers &&
6649 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6650 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6651 curproxy->id, newsrv->id,
6652 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6653 cfgerr++;
6654 goto next_srv;
6655 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006656 }
6657#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006658 if (newsrv->trackit) {
6659 struct proxy *px;
6660 struct server *srv;
6661 char *pname, *sname;
6662
6663 pname = newsrv->trackit;
6664 sname = strrchr(pname, '/');
6665
6666 if (sname)
6667 *sname++ = '\0';
6668 else {
6669 sname = pname;
6670 pname = NULL;
6671 }
6672
6673 if (pname) {
6674 px = findproxy(pname, PR_CAP_BE);
6675 if (!px) {
6676 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6677 proxy_type_str(curproxy), curproxy->id,
6678 newsrv->id, pname);
6679 cfgerr++;
6680 goto next_srv;
6681 }
6682 } else
6683 px = curproxy;
6684
6685 srv = findserver(px, sname);
6686 if (!srv) {
6687 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6688 proxy_type_str(curproxy), curproxy->id,
6689 newsrv->id, sname);
6690 cfgerr++;
6691 goto next_srv;
6692 }
6693
6694 if (!(srv->state & SRV_CHECKED)) {
6695 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6696 "tracking as it does not have checks enabled.\n",
6697 proxy_type_str(curproxy), curproxy->id,
6698 newsrv->id, px->id, srv->id);
6699 cfgerr++;
6700 goto next_srv;
6701 }
6702
6703 if (curproxy != px &&
6704 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6705 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6706 "tracking: disable-on-404 option inconsistency.\n",
6707 proxy_type_str(curproxy), curproxy->id,
6708 newsrv->id, px->id, srv->id);
6709 cfgerr++;
6710 goto next_srv;
6711 }
6712
6713 /* if the other server is forced disabled, we have to do the same here */
6714 if (srv->state & SRV_MAINTAIN) {
6715 newsrv->state |= SRV_MAINTAIN;
6716 newsrv->state &= ~SRV_RUNNING;
6717 newsrv->health = 0;
6718 }
6719
6720 newsrv->track = srv;
6721 newsrv->tracknext = srv->tracknext;
6722 srv->tracknext = newsrv;
6723
6724 free(newsrv->trackit);
6725 newsrv->trackit = NULL;
6726 }
6727 next_srv:
6728 newsrv = newsrv->next;
6729 }
6730
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006731 /* We have to initialize the server lookup mechanism depending
6732 * on what LB algorithm was choosen.
6733 */
6734
6735 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6736 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6737 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006738 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6739 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6740 init_server_map(curproxy);
6741 } else {
6742 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6743 fwrr_init_server_groups(curproxy);
6744 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006745 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006746
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006747 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006748 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6749 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6750 fwlc_init_server_tree(curproxy);
6751 } else {
6752 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6753 fas_init_server_tree(curproxy);
6754 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006755 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006756
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006757 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006758 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6759 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6760 chash_init_server_tree(curproxy);
6761 } else {
6762 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6763 init_server_map(curproxy);
6764 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006765 break;
6766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006767
6768 if (curproxy->options & PR_O_LOGASAP)
6769 curproxy->to_log &= ~LW_BYTES;
6770
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006771 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006772 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006773 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6774 proxy_type_str(curproxy), curproxy->id);
6775 err_code |= ERR_WARN;
6776 }
6777
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006778 if (curproxy->mode != PR_MODE_HTTP) {
6779 int optnum;
6780
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006781 if (curproxy->uri_auth) {
6782 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6783 proxy_type_str(curproxy), curproxy->id);
6784 err_code |= ERR_WARN;
6785 curproxy->uri_auth = NULL;
6786 }
6787
Willy Tarreau87cf5142011-08-19 22:57:24 +02006788 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006789 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6790 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6791 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006792 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006793 }
6794
6795 if (curproxy->options & PR_O_ORGTO) {
6796 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6797 "originalto", proxy_type_str(curproxy), curproxy->id);
6798 err_code |= ERR_WARN;
6799 curproxy->options &= ~PR_O_ORGTO;
6800 }
6801
6802 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6803 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6804 (curproxy->cap & cfg_opts[optnum].cap) &&
6805 (curproxy->options & cfg_opts[optnum].val)) {
6806 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6807 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6808 err_code |= ERR_WARN;
6809 curproxy->options &= ~cfg_opts[optnum].val;
6810 }
6811 }
6812
6813 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6814 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6815 (curproxy->cap & cfg_opts2[optnum].cap) &&
6816 (curproxy->options2 & cfg_opts2[optnum].val)) {
6817 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6818 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6819 err_code |= ERR_WARN;
6820 curproxy->options2 &= ~cfg_opts2[optnum].val;
6821 }
6822 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006823
Willy Tarreauefa5f512010-03-30 20:13:29 +02006824#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006825 if (curproxy->bind_hdr_occ) {
6826 curproxy->bind_hdr_occ = 0;
6827 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6828 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6829 err_code |= ERR_WARN;
6830 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006831#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006832 }
6833
Willy Tarreaubaaee002006-06-26 02:48:02 +02006834 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006835 * ensure that we're not cross-dressing a TCP server into HTTP.
6836 */
6837 newsrv = curproxy->srv;
6838 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006839 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006840 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6841 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006842 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006843 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006844
Willy Tarreau0cec3312011-10-31 13:49:26 +01006845 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6846 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6847 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6848 err_code |= ERR_WARN;
6849 }
6850
Willy Tarreauefa5f512010-03-30 20:13:29 +02006851#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006852 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6853 newsrv->bind_hdr_occ = 0;
6854 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6855 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6856 err_code |= ERR_WARN;
6857 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006858#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006859 newsrv = newsrv->next;
6860 }
6861
Willy Tarreauc1a21672009-08-16 22:37:44 +02006862 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006863 curproxy->accept = frontend_accept;
6864
Willy Tarreauc1a21672009-08-16 22:37:44 +02006865 if (curproxy->tcp_req.inspect_delay ||
6866 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006867 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006868
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006869 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006870 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006871 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006872 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006873
6874 /* both TCP and HTTP must check switching rules */
6875 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6876 }
6877
6878 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006879 if (curproxy->tcp_req.inspect_delay ||
6880 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6881 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6882
Emeric Brun97679e72010-09-23 17:56:44 +02006883 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6884 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6885
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006886 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006887 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006888 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006889 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006890
6891 /* If the backend does requires RDP cookie persistence, we have to
6892 * enable the corresponding analyser.
6893 */
6894 if (curproxy->options2 & PR_O2_RDPC_PRST)
6895 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6896 }
6897
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006898 listener = NULL;
6899 while (curproxy->listen) {
6900 struct listener *next;
6901
6902 next = curproxy->listen->next;
6903 curproxy->listen->next = listener;
6904 listener = curproxy->listen;
6905
6906 if (!next)
6907 break;
6908
6909 curproxy->listen = next;
6910 }
6911
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006912#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006913 /* Configure SSL for each bind line.
6914 * Note: if configuration fails at some point, the ->ctx member
6915 * remains NULL so that listeners can later detach.
6916 */
6917 list_for_each_entry(ssl_conf, &curproxy->conf.ssl_bind, by_fe) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006918 if (!ssl_conf->default_ctx) {
6919 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006920 curproxy->id, ssl_conf->arg, ssl_conf->file, ssl_conf->line);
6921 cfgerr++;
6922 continue;
6923 }
6924
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006925 if (shared_context_init(global.tune.sslcachesize) < 0) {
6926 Alert("Unable to allocate SSL session cache.\n");
6927 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006928 continue;
6929 }
6930
Emeric Brunfc0421f2012-09-07 17:30:07 +02006931 /* initialize all certificate contexts */
6932 cfgerr += ssl_sock_prepare_all_ctx(ssl_conf, curproxy);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006933 }
6934#endif /* USE_OPENSSL */
6935
Willy Tarreaue6b98942007-10-29 01:09:36 +01006936 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006937 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006938 listener = curproxy->listen;
6939 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006940 if (!listener->luid) {
6941 /* listener ID not set, use automatic numbering with first
6942 * spare entry starting with next_luid.
6943 */
6944 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6945 listener->conf.id.key = listener->luid = next_id;
6946 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006947 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006948 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006949
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006950 /* enable separate counters */
6951 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6952 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6953 if (!listener->name) {
6954 sprintf(trash, "sock-%d", listener->luid);
6955 listener->name = strdup(trash);
6956 }
6957 }
Emeric Brun6e159292012-05-18 16:32:13 +02006958#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006959 if (listener->ssl_conf) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006960 if (listener->ssl_conf->default_ctx) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006961 listener->data = &ssl_sock; /* SSL data layer */
Emeric Brun6e159292012-05-18 16:32:13 +02006962 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006963 else {
6964 listener->ssl_conf->ref_cnt--;
6965 listener->ssl_conf = NULL;
Emeric Brun6e159292012-05-18 16:32:13 +02006966 }
6967 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006968#endif
Willy Tarreaue6b98942007-10-29 01:09:36 +01006969 if (curproxy->options & PR_O_TCP_NOLING)
6970 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006971 if (!listener->maxconn)
6972 listener->maxconn = curproxy->maxconn;
6973 if (!listener->backlog)
6974 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006975 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006976 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006977 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006978 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006979 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006980
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006981 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6982 listener->options |= LI_O_TCP_RULES;
6983
Willy Tarreaude3041d2010-05-31 10:56:17 +02006984 if (curproxy->mon_mask.s_addr)
6985 listener->options |= LI_O_CHK_MONNET;
6986
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006987 /* smart accept mode is automatic in HTTP mode */
6988 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006989 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_conf) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006990 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6991 listener->options |= LI_O_NOQUICKACK;
6992
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006993 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006994 listener = listener->next;
6995 }
6996
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006997#ifdef USE_OPENSSL
6998 /* Release unused SSL configs.
6999 */
7000 list_for_each_entry_safe(ssl_conf, ssl_back, &curproxy->conf.ssl_bind, by_fe) {
7001 if (ssl_conf->ref_cnt)
7002 continue;
7003
Emeric Brunfc0421f2012-09-07 17:30:07 +02007004 ssl_sock_free_all_ctx(ssl_conf);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007005 free(ssl_conf->ciphers);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007006 free(ssl_conf->file);
7007 free(ssl_conf->arg);
7008 LIST_DEL(&ssl_conf->by_fe);
7009 free(ssl_conf);
7010 }
7011#endif /* USE_OPENSSL */
7012
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007013 /* Check multi-process mode compatibility for the current proxy */
7014 if (global.nbproc > 1) {
7015 int nbproc = 0;
7016 if (curproxy->bind_proc) {
7017 int proc;
7018 for (proc = 0; proc < global.nbproc; proc++) {
7019 if (curproxy->bind_proc & (1 << proc)) {
7020 nbproc++;
7021 }
7022 }
7023 } else {
7024 nbproc = global.nbproc;
7025 }
7026 if (curproxy->table.peers.name) {
7027 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7028 curproxy->id);
7029 cfgerr++;
7030 }
7031 if (nbproc > 1) {
7032 if (curproxy->uri_auth) {
7033 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7034 curproxy->id);
7035 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7036 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7037 curproxy->id);
7038 }
7039 }
7040 if (curproxy->appsession_name) {
7041 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7042 curproxy->id);
7043 }
7044 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7045 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7046 curproxy->id);
7047 }
7048 }
7049 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007050
7051 /* create the task associated with the proxy */
7052 curproxy->task = task_new();
7053 if (curproxy->task) {
7054 curproxy->task->context = curproxy;
7055 curproxy->task->process = manage_proxy;
7056 /* no need to queue, it will be done automatically if some
7057 * listener gets limited.
7058 */
7059 curproxy->task->expire = TICK_ETERNITY;
7060 } else {
7061 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7062 curproxy->id);
7063 cfgerr++;
7064 }
7065
Willy Tarreaubaaee002006-06-26 02:48:02 +02007066 curproxy = curproxy->next;
7067 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007068
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007069 /* Check multi-process mode compatibility */
7070 if (global.nbproc > 1) {
7071 if (global.stats_fe) {
7072 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
7073 }
7074 }
7075
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007076 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7077 struct auth_users *curuser;
7078 int g;
7079
7080 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7081 unsigned int group_mask = 0;
7082 char *group = NULL;
7083
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007084 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007085 continue;
7086
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007087 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007088
7089 for (g = 0; g < curuserlist->grpcnt; g++)
7090 if (!strcmp(curuserlist->groups[g], group))
7091 break;
7092
7093 if (g == curuserlist->grpcnt) {
7094 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7095 curuserlist->name, group, curuser->user);
7096 err_code |= ERR_ALERT | ERR_FATAL;
7097 goto out;
7098 }
7099
7100 group_mask |= (1 << g);
7101 }
7102
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007103 free(curuser->u.groups);
7104 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007105 }
7106
7107 for (g = 0; g < curuserlist->grpcnt; g++) {
7108 char *user = NULL;
7109
7110 if (!curuserlist->groupusers[g])
7111 continue;
7112
7113 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7114 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7115 if (!strcmp(curuser->user, user))
7116 break;
7117
7118 if (!curuser) {
7119 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7120 curuserlist->name, user, curuserlist->groups[g]);
7121 err_code |= ERR_ALERT | ERR_FATAL;
7122 goto out;
7123 }
7124
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007125 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007126 }
7127
7128 free(curuserlist->groupusers[g]);
7129 }
7130
7131 free(curuserlist->groupusers);
7132
7133#ifdef DEBUG_AUTH
7134 for (g = 0; g < curuserlist->grpcnt; g++) {
7135 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7136
7137 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007138 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007139 fprintf(stderr, " %s", curuser->user);
7140 }
7141
7142 fprintf(stderr, "\n");
7143 }
7144#endif
7145
Willy Tarreaufbb78422011-06-05 15:38:35 +02007146 }
7147
7148 /* automatically compute fullconn if not set. We must not do it in the
7149 * loop above because cross-references are not yet fully resolved.
7150 */
7151 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7152 /* If <fullconn> is not set, let's set it to 10% of the sum of
7153 * the possible incoming frontend's maxconns.
7154 */
7155 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7156 struct proxy *fe;
7157 int total = 0;
7158
7159 /* sum up the number of maxconns of frontends which
7160 * reference this backend at least once or which are
7161 * the same one ('listen').
7162 */
7163 for (fe = proxy; fe; fe = fe->next) {
7164 struct switching_rule *rule;
7165 struct hdr_exp *exp;
7166 int found = 0;
7167
7168 if (!(fe->cap & PR_CAP_FE))
7169 continue;
7170
7171 if (fe == curproxy) /* we're on a "listen" instance */
7172 found = 1;
7173
7174 if (fe->defbe.be == curproxy) /* "default_backend" */
7175 found = 1;
7176
7177 /* check if a "use_backend" rule matches */
7178 if (!found) {
7179 list_for_each_entry(rule, &fe->switching_rules, list) {
7180 if (rule->be.backend == curproxy) {
7181 found = 1;
7182 break;
7183 }
7184 }
7185 }
7186
7187 /* check if a "reqsetbe" rule matches */
7188 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7189 if (exp->action == ACT_SETBE &&
7190 (struct proxy *)exp->replace == curproxy) {
7191 found = 1;
7192 break;
7193 }
7194 }
7195
7196 /* now we've checked all possible ways to reference a backend
7197 * from a frontend.
7198 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007199 if (!found)
7200 continue;
7201 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007202 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007203 /* we have the sum of the maxconns in <total>. We only
7204 * keep 10% of that sum to set the default fullconn, with
7205 * a hard minimum of 1 (to avoid a divide by zero).
7206 */
7207 curproxy->fullconn = (total + 9) / 10;
7208 if (!curproxy->fullconn)
7209 curproxy->fullconn = 1;
7210 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007211 }
7212
Willy Tarreau056f5682010-06-06 15:51:11 +02007213 /* initialize stick-tables on backend capable proxies. This must not
7214 * be done earlier because the data size may be discovered while parsing
7215 * other proxies.
7216 */
7217 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007218 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007219
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007220 /*
7221 * Recount currently required checks.
7222 */
7223
7224 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7225 int optnum;
7226
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007227 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7228 if (curproxy->options & cfg_opts[optnum].val)
7229 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007230
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007231 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7232 if (curproxy->options2 & cfg_opts2[optnum].val)
7233 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007234 }
7235
Willy Tarreau122541c2011-09-07 21:24:49 +02007236 if (peers) {
7237 struct peers *curpeers = peers, **last;
7238 struct peer *p, *pb;
7239
7240 /* Remove all peers sections which don't have a valid listener.
7241 * This can happen when a peers section is never referenced and
7242 * does not contain a local peer.
7243 */
7244 last = &peers;
7245 while (*last) {
7246 curpeers = *last;
7247 if (curpeers->peers_fe) {
7248 last = &curpeers->next;
7249 continue;
7250 }
7251
7252 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7253 curpeers->id, localpeer);
7254
7255 p = curpeers->remote;
7256 while (p) {
7257 pb = p->next;
7258 free(p->id);
7259 free(p);
7260 p = pb;
7261 }
7262
7263 /* Destroy and unlink this curpeers section.
7264 * Note: curpeers is backed up into *last.
7265 */
7266 free(curpeers->id);
7267 curpeers = curpeers->next;
7268 free(*last);
7269 *last = curpeers;
7270 }
7271 }
7272
Willy Tarreauac1932d2011-10-24 19:14:41 +02007273 if (!global.tune.max_http_hdr)
7274 global.tune.max_http_hdr = MAX_HTTP_HDR;
7275
Willy Tarreau34eb6712011-10-24 18:15:04 +02007276 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007277 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007278 MEM_F_SHARED);
7279
Willy Tarreaubb925012009-07-23 13:36:36 +02007280 if (cfgerr > 0)
7281 err_code |= ERR_ALERT | ERR_FATAL;
7282 out:
7283 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007284}
7285
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007286/*
7287 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7288 * parsing sessions.
7289 */
7290void cfg_register_keywords(struct cfg_kw_list *kwl)
7291{
7292 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7293}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007294
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007295/*
7296 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7297 */
7298void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7299{
7300 LIST_DEL(&kwl->list);
7301 LIST_INIT(&kwl->list);
7302}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007303
7304/*
7305 * Local variables:
7306 * c-indent-level: 8
7307 * c-basic-offset: 8
7308 * End:
7309 */