blob: 6ff166e99be883faaa9428fe306caebb403fe4bc [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>
Emeric Brunaa35f1f2012-09-03 11:53:36 +020065#include <proto/shctx.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020066#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020067#ifdef USE_OPENSSL
68#include <proto/ssl_sock.h>
69#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020070#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010071#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020072
73
Willy Tarreauf3c69202006-07-09 16:42:34 +020074/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
75 * ssl-hello-chk option to ensure that the remote server speaks SSL.
76 *
77 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
78 */
79const char sslv3_client_hello_pkt[] = {
80 "\x16" /* ContentType : 0x16 = Hanshake */
81 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
82 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
83 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
84 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
85 "\x03\x00" /* Hello Version : 0x0300 = v3 */
86 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
87 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
88 "\x00" /* Session ID length : empty (no session ID) */
89 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
90 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
91 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
92 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
93 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
94 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
95 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
96 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
97 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
98 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
99 "\x00\x38" "\x00\x39" "\x00\x3A"
100 "\x01" /* Compression Length : 0x01 = 1 byte for types */
101 "\x00" /* Compression Type : 0x00 = NULL compression */
102};
103
Willy Tarreau3842f002009-06-14 11:39:52 +0200104/* various keyword modifiers */
105enum kw_mod {
106 KWM_STD = 0, /* normal */
107 KWM_NO, /* "no" prefixed before the keyword */
108 KWM_DEF, /* "default" prefixed before the keyword */
109};
110
Willy Tarreau13943ab2006-12-31 00:24:10 +0100111/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100113 const char *name;
114 unsigned int val;
115 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100116 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100118};
119
120/* proxy->options */
121static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100122{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100123 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
124 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
125 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
127 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
128 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
129 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
132 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
133 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100195static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196{
197 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100198 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 int port, end;
200
201 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200202
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203 while (next && *next) {
204 struct sockaddr_storage ss;
205
206 str = next;
207 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100208 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 *next++ = 0;
210 }
211
Emeric Bruned760922010-10-22 17:59:25 +0200212 if (*str == '/') {
213 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
214 /* so compute max path */
215 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
216 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 +0200217
Emeric Bruned760922010-10-22 17:59:25 +0200218 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100219 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
220 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200221 goto fail;
222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200225 ss.ss_family = AF_UNIX;
226 if (global.unix_bind.prefix) {
227 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
228 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
Emeric Bruned760922010-10-22 17:59:25 +0200230 else {
231 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
232 }
233 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 }
235 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 ss2 = str2sa_range(str, &port, &end);
239 if (!ss2) {
240 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
241 file, line, str);
242 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 if (!port) {
246 Alert("parsing [%s:%d] : missing port number: '%s'\n",
247 file, line, str);
248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 /* OK the address looks correct */
252 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100255 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
256 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200257 goto fail;
258 }
259
260 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100261 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
262 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 l->next = curproxy->listen;
270 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200271
272 l->fd = -1;
273 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200274 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 l->state = LI_INIT;
276
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100277 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200278 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100279 tcpv4_add_listener(l);
280 }
Emeric Bruned760922010-10-22 17:59:25 +0200281 else if (ss.ss_family == AF_INET6) {
282 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
283 tcpv6_add_listener(l);
284 }
285 else {
286 l->perm.ux.gid = l->perm.ux.uid = -1;
287 l->perm.ux.mode = 0;
288 uxst_add_listener(l);
289 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200291 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100292 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 } /* end for(port) */
294 } /* end while(next) */
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 fail:
298 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200299 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300}
301
Willy Tarreau977b8e42006-12-29 14:19:17 +0100302/*
303 * Sends a warning if proxy <proxy> does not have at least one of the
304 * capabilities in <cap>. An optionnal <hint> may be added at the end
305 * of the warning to help the user. Returns 1 if a warning was emitted
306 * or 0 if the condition is valid.
307 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100308int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100309{
310 char *msg;
311
312 switch (cap) {
313 case PR_CAP_BE: msg = "no backend"; break;
314 case PR_CAP_FE: msg = "no frontend"; break;
315 case PR_CAP_RS: msg = "no ruleset"; break;
316 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
317 default: msg = "not enough"; break;
318 }
319
320 if (!(proxy->cap & cap)) {
321 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100322 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100323 return 1;
324 }
325 return 0;
326}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200327
Willy Tarreau61d18892009-03-31 10:49:21 +0200328/* Report a warning if a rule is placed after a 'block' rule.
329 * Return 1 if the warning has been emitted, otherwise 0.
330 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100331int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200332{
333 if (!LIST_ISEMPTY(&proxy->block_cond)) {
334 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
335 file, line, arg);
336 return 1;
337 }
338 return 0;
339}
340
341/* Report a warning if a rule is placed after a reqrewrite rule.
342 * Return 1 if the warning has been emitted, otherwise 0.
343 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100344int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200345{
346 if (proxy->req_exp) {
347 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
348 file, line, arg);
349 return 1;
350 }
351 return 0;
352}
353
354/* Report a warning if a rule is placed after a reqadd rule.
355 * Return 1 if the warning has been emitted, otherwise 0.
356 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100357int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200358{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100359 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200360 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
361 file, line, arg);
362 return 1;
363 }
364 return 0;
365}
366
367/* Report a warning if a rule is placed after a redirect rule.
368 * Return 1 if the warning has been emitted, otherwise 0.
369 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100370int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200371{
372 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
373 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
374 file, line, arg);
375 return 1;
376 }
377 return 0;
378}
379
380/* Report a warning if a rule is placed after a 'use_backend' rule.
381 * Return 1 if the warning has been emitted, otherwise 0.
382 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
386 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
387 file, line, arg);
388 return 1;
389 }
390 return 0;
391}
392
393/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
397 warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
406 warnif_rule_after_redirect(proxy, file, line, arg) ||
407 warnif_rule_after_use_backend(proxy, file, line, arg);
408}
409
410/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100411int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200412{
413 return warnif_rule_after_redirect(proxy, file, line, arg) ||
414 warnif_rule_after_use_backend(proxy, file, line, arg);
415}
416
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100417/* Report it if a request ACL condition uses some response-only parameters. It
418 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
419 * Note that <cond> may be NULL and then will be ignored.
420 */
421static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
422{
423 struct acl *acl;
424
425 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
426 return 0;
427
428 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
429 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
430 file, line, acl ? acl->name : "(unknown)");
431 return ERR_WARN;
432}
433
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100434/* Report it if a request ACL condition uses some request-only volatile parameters.
435 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
436 * Note that <cond> may be NULL and then will be ignored.
437 */
438static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
439{
440 struct acl *acl;
441
442 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
443 return 0;
444
445 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
446 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
447 file, line, acl ? acl->name : "(unknown)");
448 return ERR_WARN;
449}
450
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100451
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 * parse a line in a <global> section. Returns the error code, 0 if OK, or
454 * any combination of :
455 * - ERR_ABORT: must abort ASAP
456 * - ERR_FATAL: we can continue parsing but not start the service
457 * - ERR_WARN: a warning has been emitted
458 * - ERR_ALERT: an alert has been emitted
459 * Only the two first ones can stop processing, the two others are just
460 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200462int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463{
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200465 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466
467 if (!strcmp(args[0], "global")) { /* new section */
468 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
471 else if (!strcmp(args[0], "daemon")) {
472 global.mode |= MODE_DAEMON;
473 }
474 else if (!strcmp(args[0], "debug")) {
475 global.mode |= MODE_DEBUG;
476 }
477 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100481 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200482 }
483 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100484 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200486 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100487 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100489 else if (!strcmp(args[0], "nosplice")) {
490 global.tune.options &= ~GTUNE_USE_SPLICE;
491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200492 else if (!strcmp(args[0], "quiet")) {
493 global.mode |= MODE_QUIET;
494 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 else if (!strcmp(args[0], "tune.maxpollevents")) {
496 if (global.tune.maxpollevents != 0) {
497 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 if (*(args[1]) == 0) {
502 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200503 err_code |= ERR_ALERT | ERR_FATAL;
504 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200505 }
506 global.tune.maxpollevents = atol(args[1]);
507 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 else if (!strcmp(args[0], "tune.maxaccept")) {
509 if (global.tune.maxaccept != 0) {
510 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 if (*(args[1]) == 0) {
515 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200516 err_code |= ERR_ALERT | ERR_FATAL;
517 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100518 }
519 global.tune.maxaccept = atol(args[1]);
520 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200521 else if (!strcmp(args[0], "tune.chksize")) {
522 if (*(args[1]) == 0) {
523 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
524 err_code |= ERR_ALERT | ERR_FATAL;
525 goto out;
526 }
527 global.tune.chksize = atol(args[1]);
528 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200529#ifdef USE_OPENSSL
530 else if (!strcmp(args[0], "tune.sslcachesize")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.sslcachesize = atol(args[1]);
537 }
538#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 else if (!strcmp(args[0], "tune.bufsize")) {
540 if (*(args[1]) == 0) {
541 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT | ERR_FATAL;
543 goto out;
544 }
545 global.tune.bufsize = atol(args[1]);
546 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
547 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200548 trashlen = global.tune.bufsize;
549 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 }
551 else if (!strcmp(args[0], "tune.maxrewrite")) {
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.maxrewrite = atol(args[1]);
558 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
559 global.tune.maxrewrite = global.tune.bufsize / 2;
560 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100561 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
562 if (global.tune.client_rcvbuf != 0) {
563 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT;
565 goto out;
566 }
567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.client_rcvbuf = atol(args[1]);
573 }
574 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
575 if (global.tune.server_rcvbuf != 0) {
576 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT;
578 goto out;
579 }
580 if (*(args[1]) == 0) {
581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT | ERR_FATAL;
583 goto out;
584 }
585 global.tune.server_rcvbuf = atol(args[1]);
586 }
587 else if (!strcmp(args[0], "tune.sndbuf.client")) {
588 if (global.tune.client_sndbuf != 0) {
589 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
590 err_code |= ERR_ALERT;
591 goto out;
592 }
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.client_sndbuf = atol(args[1]);
599 }
600 else if (!strcmp(args[0], "tune.sndbuf.server")) {
601 if (global.tune.server_sndbuf != 0) {
602 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT;
604 goto out;
605 }
606 if (*(args[1]) == 0) {
607 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611 global.tune.server_sndbuf = atol(args[1]);
612 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200613 else if (!strcmp(args[0], "tune.pipesize")) {
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
618 }
619 global.tune.pipesize = atol(args[1]);
620 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200621 else if (!strcmp(args[0], "tune.http.maxhdr")) {
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.max_http_hdr = atol(args[1]);
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "uid")) {
630 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT;
633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200639 }
640 global.uid = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "gid")) {
643 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
653 global.gid = atol(args[1]);
654 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200655 /* user/group name handling */
656 else if (!strcmp(args[0], "user")) {
657 struct passwd *ha_user;
658 if (global.uid != 0) {
659 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT;
661 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200662 }
663 errno = 0;
664 ha_user = getpwnam(args[1]);
665 if (ha_user != NULL) {
666 global.uid = (int)ha_user->pw_uid;
667 }
668 else {
669 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 +0200670 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200671 }
672 }
673 else if (!strcmp(args[0], "group")) {
674 struct group *ha_group;
675 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200676 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200679 }
680 errno = 0;
681 ha_group = getgrnam(args[1]);
682 if (ha_group != NULL) {
683 global.gid = (int)ha_group->gr_gid;
684 }
685 else {
686 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 +0200687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200688 }
689 }
690 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 else if (!strcmp(args[0], "nbproc")) {
692 if (global.nbproc != 0) {
693 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT;
695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200696 }
697 if (*(args[1]) == 0) {
698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 }
702 global.nbproc = atol(args[1]);
703 }
704 else if (!strcmp(args[0], "maxconn")) {
705 if (global.maxconn != 0) {
706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200707 err_code |= ERR_ALERT;
708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200709 }
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200714 }
715 global.maxconn = atol(args[1]);
716#ifdef SYSTEM_MAXCONN
717 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
718 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);
719 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200720 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722#endif /* SYSTEM_MAXCONN */
723 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200724 else if (!strcmp(args[0], "maxconnrate")) {
725 if (global.cps_lim != 0) {
726 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT;
728 goto out;
729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735 global.cps_lim = atol(args[1]);
736 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100737 else if (!strcmp(args[0], "maxpipes")) {
738 if (global.maxpipes != 0) {
739 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT;
741 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100742 }
743 if (*(args[1]) == 0) {
744 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100747 }
748 global.maxpipes = atol(args[1]);
749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200750 else if (!strcmp(args[0], "ulimit-n")) {
751 if (global.rlimit_nofile != 0) {
752 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 err_code |= ERR_ALERT;
754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200755 }
756 if (*(args[1]) == 0) {
757 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200758 err_code |= ERR_ALERT | ERR_FATAL;
759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200760 }
761 global.rlimit_nofile = atol(args[1]);
762 }
763 else if (!strcmp(args[0], "chroot")) {
764 if (global.chroot != NULL) {
765 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200766 err_code |= ERR_ALERT;
767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200768 }
769 if (*(args[1]) == 0) {
770 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200771 err_code |= ERR_ALERT | ERR_FATAL;
772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200773 }
774 global.chroot = strdup(args[1]);
775 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200776 else if (!strcmp(args[0], "description")) {
777 int i, len=0;
778 char *d;
779
780 if (!*args[1]) {
781 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
782 file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786
787 for(i=1; *args[i]; i++)
788 len += strlen(args[i])+1;
789
790 if (global.desc)
791 free(global.desc);
792
793 global.desc = d = (char *)calloc(1, len);
794
795 d += sprintf(d, "%s", args[1]);
796 for(i=2; *args[i]; i++)
797 d += sprintf(d, " %s", args[i]);
798 }
799 else if (!strcmp(args[0], "node")) {
800 int i;
801 char c;
802
803 for (i=0; args[1][i]; i++) {
804 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100805 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
806 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200807 break;
808 }
809
810 if (!i || args[1][i]) {
811 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
812 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
813 file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817
818 if (global.node)
819 free(global.node);
820
821 global.node = strdup(args[1]);
822 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 else if (!strcmp(args[0], "pidfile")) {
824 if (global.pidfile != NULL) {
825 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT;
827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 }
829 if (*(args[1]) == 0) {
830 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200831 err_code |= ERR_ALERT | ERR_FATAL;
832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200833 }
834 global.pidfile = strdup(args[1]);
835 }
Emeric Bruned760922010-10-22 17:59:25 +0200836 else if (!strcmp(args[0], "unix-bind")) {
837 int cur_arg = 1;
838 while (*(args[cur_arg])) {
839 if (!strcmp(args[cur_arg], "prefix")) {
840 if (global.unix_bind.prefix != NULL) {
841 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
842 err_code |= ERR_ALERT;
843 cur_arg += 2;
844 continue;
845 }
846
847 if (*(args[cur_arg+1]) == 0) {
848 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852 global.unix_bind.prefix = strdup(args[cur_arg+1]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "mode")) {
858
859 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
860 cur_arg += 2;
861 continue;
862 }
863
864 if (!strcmp(args[cur_arg], "uid")) {
865
866 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
867 cur_arg += 2;
868 continue;
869 }
870
871 if (!strcmp(args[cur_arg], "gid")) {
872
873 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
874 cur_arg += 2;
875 continue;
876 }
877
878 if (!strcmp(args[cur_arg], "user")) {
879 struct passwd *user;
880
881 user = getpwnam(args[cur_arg + 1]);
882 if (!user) {
883 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
884 file, linenum, args[0], args[cur_arg + 1 ]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888
889 global.unix_bind.ux.uid = user->pw_uid;
890 cur_arg += 2;
891 continue;
892 }
893
894 if (!strcmp(args[cur_arg], "group")) {
895 struct group *group;
896
897 group = getgrnam(args[cur_arg + 1]);
898 if (!group) {
899 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
900 file, linenum, args[0], args[cur_arg + 1 ]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 global.unix_bind.ux.gid = group->gr_gid;
906 cur_arg += 2;
907 continue;
908 }
909
Willy Tarreaub48f9582011-09-05 01:17:06 +0200910 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200911 file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915 }
William Lallemand0f99e342011-10-12 17:50:54 +0200916 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
917 /* delete previous herited or defined syslog servers */
918 struct logsrv *back;
919 struct logsrv *tmp;
920
921 if (*(args[1]) != 0) {
922 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926
927 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
928 LIST_DEL(&tmp->list);
929 free(tmp);
930 }
931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200933 struct logsrv *logsrv;
934
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 if (*(args[1]) == 0 || *(args[2]) == 0) {
936 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200937 err_code |= ERR_ALERT | ERR_FATAL;
938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
William Lallemand0f99e342011-10-12 17:50:54 +0200940
941 logsrv = calloc(1, sizeof(struct logsrv));
942
943 logsrv->facility = get_log_facility(args[2]);
944 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200946 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200947 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949
William Lallemand0f99e342011-10-12 17:50:54 +0200950 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200952 logsrv->level = get_log_level(args[3]);
953 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200956 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 }
959
William Lallemand0f99e342011-10-12 17:50:54 +0200960 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200961 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200962 logsrv->minlvl = get_log_level(args[4]);
963 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200964 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200965 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200967 }
968 }
969
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100971 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100972 if (!sk) {
973 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100974 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100975 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200976 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100977 goto out;
978 }
William Lallemand0f99e342011-10-12 17:50:54 +0200979 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100980 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100981 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100982 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100983 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
984 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200985 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100986 goto out;
987 }
William Lallemand0f99e342011-10-12 17:50:54 +0200988 logsrv->addr = *sk;
989 if (!get_host_port(&logsrv->addr))
990 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992
William Lallemand0f99e342011-10-12 17:50:54 +0200993 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200994 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100995 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
996 char *name;
997 int len;
998
999 if (global.log_send_hostname != NULL) {
1000 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT;
1002 goto out;
1003 }
1004
1005 if (*(args[1]))
1006 name = args[1];
1007 else
1008 name = hostname;
1009
1010 len = strlen(name);
1011
1012 /* We'll add a space after the name to respect the log format */
1013 free(global.log_send_hostname);
1014 global.log_send_hostname = malloc(len + 2);
1015 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1016 }
Kevinm48936af2010-12-22 16:08:21 +00001017 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1018 if (*(args[1]) == 0) {
1019 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 free(global.log_tag);
1024 global.log_tag = strdup(args[1]);
1025 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001026 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1027 if (global.spread_checks != 0) {
1028 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT;
1030 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001031 }
1032 if (*(args[1]) == 0) {
1033 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001036 }
1037 global.spread_checks = atol(args[1]);
1038 if (global.spread_checks < 0 || global.spread_checks > 50) {
1039 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 struct cfg_kw_list *kwl;
1045 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001047
1048 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1049 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1050 if (kwl->kw[index].section != CFG_GLOBAL)
1051 continue;
1052 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1053 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001054 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001055 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001056 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001057 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001058 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001059 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001060 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001061 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001062 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 err_code |= ERR_WARN;
1064 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001065 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001067 }
1068 }
1069 }
1070
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001074
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001076 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078}
1079
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001080void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001081{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001082 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 defproxy.mode = PR_MODE_TCP;
1084 defproxy.state = PR_STNEW;
1085 defproxy.maxconn = cfg_maxpconn;
1086 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001087
1088 defproxy.defsrv.inter = DEF_CHKINTR;
1089 defproxy.defsrv.fastinter = 0;
1090 defproxy.defsrv.downinter = 0;
1091 defproxy.defsrv.rise = DEF_RISETIME;
1092 defproxy.defsrv.fall = DEF_FALLTIME;
1093 defproxy.defsrv.check_port = 0;
1094 defproxy.defsrv.maxqueue = 0;
1095 defproxy.defsrv.minconn = 0;
1096 defproxy.defsrv.maxconn = 0;
1097 defproxy.defsrv.slowstart = 0;
1098 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1099 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1100 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101}
1102
Willy Tarreauade5ec42010-01-28 19:33:49 +01001103
1104static int create_cond_regex_rule(const char *file, int line,
1105 struct proxy *px, int dir, int action, int flags,
1106 const char *cmd, const char *reg, const char *repl,
1107 const char **cond_start)
1108{
1109 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001110 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001111 const char *err;
1112 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001113 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114
1115 if (px == &defproxy) {
1116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1117 err_code |= ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (*reg == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1128 err_code |= ERR_WARN;
1129
Willy Tarreau5321c422010-01-28 20:35:13 +01001130 if (cond_start &&
1131 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001132 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1133 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1134 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001135 err_code |= ERR_ALERT | ERR_FATAL;
1136 goto err;
1137 }
1138 }
1139 else if (cond_start && **cond_start) {
1140 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1141 file, line, cmd, *cond_start);
1142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto err;
1144 }
1145
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001146 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001147 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001148 else
1149 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001150
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 preg = calloc(1, sizeof(regex_t));
1152 if (!preg) {
1153 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1154 err_code = ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
1158 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1159 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1160 err_code = ERR_ALERT | ERR_FATAL;
1161 goto err;
1162 }
1163
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001164 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001165 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 if (repl && err) {
1167 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1168 file, line, cmd, *err);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 goto err;
1171 }
1172
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001173 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001174 err_code |= ERR_WARN;
1175
Willy Tarreauf4068b62012-05-08 17:37:49 +02001176 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001177 return err_code;
1178 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001179 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001180 free(preg);
1181 return err_code;
1182}
1183
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001185 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001186 * Returns the error code, 0 if OK, or any combination of :
1187 * - ERR_ABORT: must abort ASAP
1188 * - ERR_FATAL: we can continue parsing but not start the service
1189 * - ERR_WARN: a warning has been emitted
1190 * - ERR_ALERT: an alert has been emitted
1191 * Only the two first ones can stop processing, the two others are just
1192 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001194int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1195{
1196 static struct peers *curpeers = NULL;
1197 struct peer *newpeer = NULL;
1198 const char *err;
1199 int err_code = 0;
1200
1201 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1202
1203 err = invalid_char(args[1]);
1204 if (err) {
1205 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1206 file, linenum, *err, args[0], args[1]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 }
1209
1210 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1211 /*
1212 * If there are two proxies with the same name only following
1213 * combinations are allowed:
1214 */
1215 if (strcmp(curpeers->id, args[1]) == 0) {
1216 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1217 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1218 err_code |= ERR_WARN;
1219 }
1220 }
1221
1222 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1224 err_code |= ERR_ALERT | ERR_ABORT;
1225 goto out;
1226 }
1227
1228 curpeers->next = peers;
1229 peers = curpeers;
1230 curpeers->conf.file = file;
1231 curpeers->conf.line = linenum;
1232 curpeers->last_change = now.tv_sec;
1233 curpeers->id = strdup(args[1]);
1234 }
1235 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1236 char *rport, *raddr;
1237 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001238 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001239
1240 if (!*args[2]) {
1241 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1242 file, linenum, args[0]);
1243 err_code |= ERR_ALERT | ERR_FATAL;
1244 goto out;
1245 }
1246
1247 err = invalid_char(args[1]);
1248 if (err) {
1249 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1250 file, linenum, *err, args[1]);
1251 err_code |= ERR_ALERT | ERR_FATAL;
1252 goto out;
1253 }
1254
1255 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1256 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1257 err_code |= ERR_ALERT | ERR_ABORT;
1258 goto out;
1259 }
1260
1261 /* the peers are linked backwards first */
1262 curpeers->count++;
1263 newpeer->next = curpeers->remote;
1264 curpeers->remote = newpeer;
1265 newpeer->peers = curpeers;
1266 newpeer->conf.file = file;
1267 newpeer->conf.line = linenum;
1268
1269 newpeer->last_change = now.tv_sec;
1270 newpeer->id = strdup(args[1]);
1271
1272 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001273 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001274 if (rport) {
1275 *rport++ = 0;
1276 realport = atol(rport);
1277 }
1278 if (!realport) {
1279 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1280 err_code |= ERR_ALERT | ERR_FATAL;
1281 goto out;
1282 }
1283
Willy Tarreaufab5a432011-03-04 15:31:53 +01001284 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001285 free(raddr);
1286 if (!sk) {
1287 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001292 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001293 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001294 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001295
1296 if (!sk) {
1297 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1298 file, linenum, newpeer->addr.ss_family, args[2]);
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001303 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001304
1305 if (strcmp(newpeer->id, localpeer) == 0) {
1306 /* Current is local peer, it define a frontend */
1307 newpeer->local = 1;
1308
1309 if (!curpeers->peers_fe) {
1310 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1312 err_code |= ERR_ALERT | ERR_ABORT;
1313 goto out;
1314 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001315
Willy Tarreau237250c2011-07-29 01:49:03 +02001316 init_new_proxy(curpeers->peers_fe);
1317 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001318
1319 curpeers->peers_fe->last_change = now.tv_sec;
1320 curpeers->peers_fe->id = strdup(args[1]);
1321 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001322 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001323 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1324 curpeers->peers_fe->timeout.connect = 5000;
1325 curpeers->peers_fe->accept = peer_accept;
1326 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001327 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001328 err_code |= ERR_FATAL;
1329 goto out;
1330 }
1331 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1332 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1333 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1334 curpeers->peers_fe->listen->accept = session_accept;
1335 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1336 curpeers->peers_fe->listen->handler = process_session;
1337 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001338 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1339 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001340 }
1341 }
1342 } /* neither "peer" nor "peers" */
1343 else if (*args[0] != 0) {
1344 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1345 err_code |= ERR_ALERT | ERR_FATAL;
1346 goto out;
1347 }
1348
1349out:
1350 return err_code;
1351}
1352
1353
Willy Tarreau3842f002009-06-14 11:39:52 +02001354int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355{
1356 static struct proxy *curproxy = NULL;
1357 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001358 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001359 int rc;
1360 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001361 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001362 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001363 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001364 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365
Willy Tarreau977b8e42006-12-29 14:19:17 +01001366 if (!strcmp(args[0], "listen"))
1367 rc = PR_CAP_LISTEN;
1368 else if (!strcmp(args[0], "frontend"))
1369 rc = PR_CAP_FE | PR_CAP_RS;
1370 else if (!strcmp(args[0], "backend"))
1371 rc = PR_CAP_BE | PR_CAP_RS;
1372 else if (!strcmp(args[0], "ruleset"))
1373 rc = PR_CAP_RS;
1374 else
1375 rc = PR_CAP_NONE;
1376
1377 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 if (!*args[1]) {
1379 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1380 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_ABORT;
1383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001385
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001386 err = invalid_char(args[1]);
1387 if (err) {
1388 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1389 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001391 }
1392
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001393 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1394 /*
1395 * If there are two proxies with the same name only following
1396 * combinations are allowed:
1397 *
1398 * listen backend frontend ruleset
1399 * listen - - - -
1400 * backend - - OK -
1401 * frontend - OK - -
1402 * ruleset - - - -
1403 */
1404
1405 if (!strcmp(curproxy->id, args[1]) &&
1406 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1407 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001408 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1409 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1410 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001411 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001412 }
1413 }
1414
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1416 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001417 err_code |= ERR_ALERT | ERR_ABORT;
1418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001420
Willy Tarreau97cb7802010-01-03 20:23:58 +01001421 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 curproxy->next = proxy;
1423 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001424 curproxy->conf.file = file;
1425 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001426 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001428 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429
1430 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001431 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001432 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001433 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001434 err_code |= ERR_FATAL;
1435 goto out;
1436 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001437 new = curproxy->listen;
1438 while (new != last) {
1439 new->conf.file = file;
1440 new->conf.line = linenum;
1441 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001442 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001443 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444 }
1445
1446 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001447 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001448 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001449
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001452 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001453 curproxy->no_options = defproxy.no_options;
1454 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001455 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001456 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001457 curproxy->except_net = defproxy.except_net;
1458 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001459 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001460 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001462 if (defproxy.fwdfor_hdr_len) {
1463 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1464 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1465 }
1466
Willy Tarreaub86db342009-11-30 11:50:16 +01001467 if (defproxy.orgto_hdr_len) {
1468 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1469 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1470 }
1471
Mark Lamourinec2247f02012-01-04 13:02:01 -05001472 if (defproxy.server_id_hdr_len) {
1473 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1474 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1475 }
1476
Willy Tarreau977b8e42006-12-29 14:19:17 +01001477 if (curproxy->cap & PR_CAP_FE) {
1478 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001479 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001480 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001481
1482 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001483 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1484 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001485
1486 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 if (curproxy->cap & PR_CAP_BE) {
1490 curproxy->fullconn = defproxy.fullconn;
1491 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001493 if (defproxy.check_req) {
1494 curproxy->check_req = calloc(1, defproxy.check_len);
1495 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1496 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001499 if (defproxy.expect_str) {
1500 curproxy->expect_str = strdup(defproxy.expect_str);
1501 if (defproxy.expect_regex) {
1502 /* note: this regex is known to be valid */
1503 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1504 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1505 }
1506 }
1507
Willy Tarreau67402132012-05-31 20:40:20 +02001508 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (defproxy.cookie_name)
1510 curproxy->cookie_name = strdup(defproxy.cookie_name);
1511 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001512 if (defproxy.cookie_domain)
1513 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001514
Willy Tarreau31936852010-10-06 16:59:56 +02001515 if (defproxy.cookie_maxidle)
1516 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1517
1518 if (defproxy.cookie_maxlife)
1519 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1520
Emeric Brun647caf12009-06-30 17:57:00 +02001521 if (defproxy.rdp_cookie_name)
1522 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1523 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1524
Willy Tarreau01732802007-11-01 22:48:15 +01001525 if (defproxy.url_param_name)
1526 curproxy->url_param_name = strdup(defproxy.url_param_name);
1527 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001528
Benoitaffb4812009-03-25 13:02:10 +01001529 if (defproxy.hh_name)
1530 curproxy->hh_name = strdup(defproxy.hh_name);
1531 curproxy->hh_len = defproxy.hh_len;
1532 curproxy->hh_match_domain = defproxy.hh_match_domain;
1533
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001534 if (defproxy.iface_name)
1535 curproxy->iface_name = strdup(defproxy.iface_name);
1536 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001539 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 if (defproxy.capture_name)
1541 curproxy->capture_name = strdup(defproxy.capture_name);
1542 curproxy->capture_namelen = defproxy.capture_namelen;
1543 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001544 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545
Willy Tarreau977b8e42006-12-29 14:19:17 +01001546 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001547 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001548 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001549 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001550 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001551 curproxy->uri_auth = defproxy.uri_auth;
1552 curproxy->mon_net = defproxy.mon_net;
1553 curproxy->mon_mask = defproxy.mon_mask;
1554 if (defproxy.monitor_uri)
1555 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1556 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001557 if (defproxy.defbe.name)
1558 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001559
1560 /* get either a pointer to the logformat string or a copy of it */
1561 curproxy->logformat_string = defproxy.logformat_string;
1562 if (curproxy->logformat_string &&
1563 curproxy->logformat_string != default_http_log_format &&
1564 curproxy->logformat_string != default_tcp_log_format &&
1565 curproxy->logformat_string != clf_http_log_format)
1566 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 }
1568
1569 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001570 curproxy->timeout.connect = defproxy.timeout.connect;
1571 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001572 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001573 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001574 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001575 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001576 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001577 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001578 curproxy->source_addr = defproxy.source_addr;
1579 }
1580
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001582
1583 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001584 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001585 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001586 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001587 LIST_INIT(&node->list);
1588 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1589 }
1590
Willy Tarreau196729e2012-05-31 19:30:26 +02001591 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1592 if (curproxy->uniqueid_format_string)
1593 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001594
1595 /* copy default header unique id */
1596 if (defproxy.header_unique_id)
1597 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001600 curproxy->conf.used_listener_id = EB_ROOT;
1601 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001602
Willy Tarreau93893792009-07-23 13:19:11 +02001603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
1605 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1606 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001607 /* FIXME-20070101: we should do this too at the end of the
1608 * config parsing to free all default values.
1609 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001610 free(defproxy.check_req);
1611 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001612 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001613 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001614 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001615 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001616 free(defproxy.capture_name);
1617 free(defproxy.monitor_uri);
1618 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001619 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001620 free(defproxy.fwdfor_hdr_name);
1621 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001622 free(defproxy.orgto_hdr_name);
1623 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001624 free(defproxy.server_id_hdr_name);
1625 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001626 free(defproxy.expect_str);
1627 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001628
Willy Tarreau39b06652012-06-01 10:58:06 +02001629 if (defproxy.logformat_string != default_http_log_format &&
1630 defproxy.logformat_string != default_tcp_log_format &&
1631 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001632 free(defproxy.logformat_string);
1633
1634 free(defproxy.uniqueid_format_string);
1635
Willy Tarreaua534fea2008-08-03 12:19:50 +02001636 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001637 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001638
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 /* we cannot free uri_auth because it might already be used */
1640 init_default_instance();
1641 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001642 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001643 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001644 }
1645 else if (curproxy == NULL) {
1646 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001647 err_code |= ERR_ALERT | ERR_FATAL;
1648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 }
1650
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651
1652 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001654 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655 int cur_arg;
1656
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 if (curproxy == &defproxy) {
1658 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001663 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001664
Emeric Bruned760922010-10-22 17:59:25 +02001665 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001666 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001671
1672 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001673
1674 /* NOTE: the following line might create several listeners if there
1675 * are comma-separated IPs or port ranges. So all further processing
1676 * will have to be applied to all listeners created after last_listen.
1677 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001678 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
1681 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001682
Willy Tarreau90a570f2009-10-04 20:54:54 +02001683 new_listen = curproxy->listen;
1684 while (new_listen != last_listen) {
1685 new_listen->conf.file = file;
1686 new_listen->conf.line = linenum;
1687 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001688 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001689 }
1690
Emeric Bruned760922010-10-22 17:59:25 +02001691 /* Set default global rights and owner for unix bind */
1692 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1693 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1694 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001695 cur_arg = 2;
1696 while (*(args[cur_arg])) {
1697 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1698#ifdef SO_BINDTODEVICE
1699 struct listener *l;
1700
Emeric Bruned760922010-10-22 17:59:25 +02001701 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1702 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1703 file, linenum, args[0], args[cur_arg]);
1704 err_code |= ERR_ALERT | ERR_FATAL;
1705 goto out;
1706 }
1707
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001708 if (!*args[cur_arg + 1]) {
1709 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713 }
1714
1715 for (l = curproxy->listen; l != last_listen; l = l->next)
1716 l->interface = strdup(args[cur_arg + 1]);
1717
1718 global.last_checks |= LSTCHK_NETADM;
1719
1720 cur_arg += 2;
1721 continue;
1722#else
1723 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001725 err_code |= ERR_ALERT | ERR_FATAL;
1726 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001727#endif
1728 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001729 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1730#ifdef TCP_MAXSEG
1731 struct listener *l;
1732 int mss;
1733
Emeric Bruned760922010-10-22 17:59:25 +02001734 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1735 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1736 file, linenum, args[0], args[cur_arg]);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739 }
1740
Willy Tarreaube1b9182009-06-14 18:48:19 +02001741 if (!*args[cur_arg + 1]) {
1742 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001746 }
1747
Willy Tarreau48a7e722010-12-24 15:26:39 +01001748 mss = atoi(args[cur_arg + 1]);
1749 if (!mss || abs(mss) > 65535) {
1750 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001751 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001754 }
1755
1756 for (l = curproxy->listen; l != last_listen; l = l->next)
1757 l->maxseg = mss;
1758
1759 cur_arg += 2;
1760 continue;
1761#else
1762 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1763 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001766#endif
1767 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001768
1769 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1770#ifdef TCP_DEFER_ACCEPT
1771 struct listener *l;
1772
1773 for (l = curproxy->listen; l != last_listen; l = l->next)
1774 l->options |= LI_O_DEF_ACCEPT;
1775
1776 cur_arg ++;
1777 continue;
1778#else
1779 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1780 file, linenum, args[0], args[cur_arg]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783#endif
1784 }
1785
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001786 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001787#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001788 struct listener *l;
1789
Emeric Bruned760922010-10-22 17:59:25 +02001790 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001797 for (l = curproxy->listen; l != last_listen; l = l->next)
1798 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001799
1800 cur_arg ++;
1801 continue;
1802#else
1803 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1804 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001807#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001808 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001809
Emeric Brun6e159292012-05-18 16:32:13 +02001810 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1811#ifdef USE_OPENSSL
1812 struct listener *l;
1813
1814 if (!*args[cur_arg + 1]) {
1815 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1816 file, linenum, args[0]);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 for (l = curproxy->listen; l != last_listen; l = l->next)
1822 l->ssl_cert = strdup(args[cur_arg + 1]);
1823
1824 cur_arg += 2;
1825 continue;
1826#else
1827 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1828 file, linenum, args[0], args[cur_arg]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831#endif
1832 }
1833
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02001834 if (!strcmp(args[cur_arg], "ciphers")) { /* set cipher suite */
1835#ifdef USE_OPENSSL
1836 struct listener *l;
1837
1838 if (!*args[cur_arg + 1]) {
1839 Alert("parsing [%s:%d] : '%s' : missing cipher suite.\n",
1840 file, linenum, args[0]);
1841 err_code |= ERR_ALERT | ERR_FATAL;
1842 goto out;
1843 }
1844
1845 for (l = curproxy->listen; l != last_listen; l = l->next)
1846 l->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
1847
1848 cur_arg += 2;
1849 continue;
1850#else
1851 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1852 file, linenum, args[0], args[cur_arg]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855#endif
1856 }
1857
Willy Tarreauc230b8b2012-09-03 23:55:16 +02001858 if (!strcmp(args[cur_arg], "nosslv3")) { /* disable SSLv3 */
1859#ifdef USE_OPENSSL
1860 struct listener *l;
1861
1862 for (l = curproxy->listen; l != last_listen; l = l->next)
1863 l->ssl_ctx.nosslv3 = 1;
1864
1865 cur_arg += 1;
1866 continue;
1867#else
1868 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1869 file, linenum, args[0], args[cur_arg]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872#endif
1873 }
1874
1875 if (!strcmp(args[cur_arg], "notlsv1")) { /* disable TLSv1 */
1876#ifdef USE_OPENSSL
1877 struct listener *l;
1878
1879 for (l = curproxy->listen; l != last_listen; l = l->next)
1880 l->ssl_ctx.notlsv1 = 1;
1881
1882 cur_arg += 1;
1883 continue;
1884#else
1885 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1886 file, linenum, args[0], args[cur_arg]);
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889#endif
1890 }
1891
David BERARDe566ecb2012-09-04 15:15:13 +02001892 if (!strcmp(args[cur_arg], "prefer-server-ciphers")) { /* Prefert server ciphers */
1893#if defined (USE_OPENSSL) && defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
1894 struct listener *l;
1895
1896 for (l = curproxy->listen; l != last_listen; l = l->next)
1897 l->ssl_ctx.prefer_server_ciphers = 1;
1898
1899 cur_arg += 1;
1900 continue;
1901#else
1902 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1903 file, linenum, args[0], args[cur_arg]);
1904 err_code |= ERR_ALERT | ERR_FATAL;
1905 goto out;
1906#endif
1907 }
1908
Willy Tarreau8a956912010-10-15 14:27:08 +02001909 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1910 struct listener *l;
1911
1912 for (l = curproxy->listen; l != last_listen; l = l->next)
1913 l->options |= LI_O_ACC_PROXY;
1914
1915 cur_arg ++;
1916 continue;
1917 }
1918
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001919 if (!strcmp(args[cur_arg], "name")) {
1920 struct listener *l;
1921
1922 for (l = curproxy->listen; l != last_listen; l = l->next)
1923 l->name = strdup(args[cur_arg + 1]);
1924
1925 cur_arg += 2;
1926 continue;
1927 }
1928
1929 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001930 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001931 struct listener *l;
1932
1933 if (curproxy->listen->next != last_listen) {
1934 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1935 file, linenum, args[cur_arg]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940 if (!*args[cur_arg + 1]) {
1941 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1942 file, linenum, args[cur_arg]);
1943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
1945 }
1946
1947 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001948 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001949
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001950 if (curproxy->listen->luid <= 0) {
1951 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001952 file, linenum);
1953 err_code |= ERR_ALERT | ERR_FATAL;
1954 goto out;
1955 }
1956
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001957 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1958 if (node) {
1959 l = container_of(node, struct listener, conf.id);
1960 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1961 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
1964 }
1965 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1966
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001967 cur_arg += 2;
1968 continue;
1969 }
1970
Emeric Bruned760922010-10-22 17:59:25 +02001971 if (!strcmp(args[cur_arg], "mode")) {
1972
1973 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1974 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1975 file, linenum, args[0], args[cur_arg]);
1976 err_code |= ERR_ALERT | ERR_FATAL;
1977 goto out;
1978 }
1979
1980 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1981
1982 cur_arg += 2;
1983 continue;
1984 }
1985
1986 if (!strcmp(args[cur_arg], "uid")) {
1987
1988 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1989 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1990 file, linenum, args[0], args[cur_arg]);
1991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
1993 }
1994
1995 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1996 cur_arg += 2;
1997 continue;
1998 }
1999
2000 if (!strcmp(args[cur_arg], "gid")) {
2001
2002 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2003 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2004 file, linenum, args[0], args[cur_arg]);
2005 err_code |= ERR_ALERT | ERR_FATAL;
2006 goto out;
2007 }
2008
2009 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
2010 cur_arg += 2;
2011 continue;
2012 }
2013
2014 if (!strcmp(args[cur_arg], "user")) {
2015 struct passwd *user;
2016
2017 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2018 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2019 file, linenum, args[0], args[cur_arg]);
2020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
2022 }
2023 user = getpwnam(args[cur_arg + 1]);
2024 if (!user) {
2025 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
2026 file, linenum, args[0], args[cur_arg + 1 ]);
2027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030
2031 curproxy->listen->perm.ux.uid = user->pw_uid;
2032 cur_arg += 2;
2033 continue;
2034 }
2035
2036 if (!strcmp(args[cur_arg], "group")) {
2037 struct group *group;
2038
2039 if (curproxy->listen->addr.ss_family != AF_UNIX) {
2040 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
2041 file, linenum, args[0], args[cur_arg]);
2042 err_code |= ERR_ALERT | ERR_FATAL;
2043 goto out;
2044 }
2045 group = getgrnam(args[cur_arg + 1]);
2046 if (!group) {
2047 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
2048 file, linenum, args[0], args[cur_arg + 1 ]);
2049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
2051 }
2052
2053 curproxy->listen->perm.ux.gid = group->gr_gid;
2054 cur_arg += 2;
2055 continue;
2056 }
2057
Willy Tarreaub48f9582011-09-05 01:17:06 +02002058 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 +01002059 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002062 }
Willy Tarreau93893792009-07-23 13:19:11 +02002063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 }
2065 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2066 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2067 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2068 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_ALERT | ERR_FATAL;
2070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002072 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 /* flush useless bits */
2076 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002079 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002080 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002081 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002082
Willy Tarreau1c47f852006-07-09 08:22:27 +02002083 if (!*args[1]) {
2084 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002088 }
2089
Willy Tarreaua534fea2008-08-03 12:19:50 +02002090 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002091 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002092 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002093 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002094 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2095
Willy Tarreau93893792009-07-23 13:19:11 +02002096 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2099 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2100 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2101 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2102 else {
2103 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
2107 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002108 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002109 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002110
2111 if (curproxy == &defproxy) {
2112 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2113 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002114 err_code |= ERR_ALERT | ERR_FATAL;
2115 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002116 }
2117
2118 if (!*args[1]) {
2119 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002123 }
2124
2125 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002126 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002127
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002128 if (curproxy->uuid <= 0) {
2129 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002130 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002133 }
2134
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002135 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2136 if (node) {
2137 struct proxy *target = container_of(node, struct proxy, conf.id);
2138 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2139 file, linenum, proxy_type_str(curproxy), curproxy->id,
2140 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
2143 }
2144 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002145 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002146 else if (!strcmp(args[0], "description")) {
2147 int i, len=0;
2148 char *d;
2149
Cyril Bonté99ed3272010-01-24 23:29:44 +01002150 if (curproxy == &defproxy) {
2151 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2152 file, linenum, args[0]);
2153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
2155 }
2156
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002157 if (!*args[1]) {
2158 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2159 file, linenum, args[0]);
2160 return -1;
2161 }
2162
2163 for(i=1; *args[i]; i++)
2164 len += strlen(args[i])+1;
2165
2166 d = (char *)calloc(1, len);
2167 curproxy->desc = d;
2168
2169 d += sprintf(d, "%s", args[1]);
2170 for(i=2; *args[i]; i++)
2171 d += sprintf(d, " %s", args[i]);
2172
2173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2175 curproxy->state = PR_STSTOPPED;
2176 }
2177 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2178 curproxy->state = PR_STNEW;
2179 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002180 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2181 int cur_arg = 1;
2182 unsigned int set = 0;
2183
2184 while (*args[cur_arg]) {
2185 int u;
2186 if (strcmp(args[cur_arg], "all") == 0) {
2187 set = 0;
2188 break;
2189 }
2190 else if (strcmp(args[cur_arg], "odd") == 0) {
2191 set |= 0x55555555;
2192 }
2193 else if (strcmp(args[cur_arg], "even") == 0) {
2194 set |= 0xAAAAAAAA;
2195 }
2196 else {
2197 u = str2uic(args[cur_arg]);
2198 if (u < 1 || u > 32) {
2199 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002203 }
2204 if (u > global.nbproc) {
2205 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002208 }
2209 set |= 1 << (u - 1);
2210 }
2211 cur_arg++;
2212 }
2213 curproxy->bind_proc = set;
2214 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002215 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002216 if (curproxy == &defproxy) {
2217 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002220 }
2221
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002222 err = invalid_char(args[1]);
2223 if (err) {
2224 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2225 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002227 }
2228
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002229 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2230 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2231 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002234 }
2235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2237 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238
Willy Tarreau977b8e42006-12-29 14:19:17 +01002239 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002241
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 if (*(args[1]) == 0) {
2243 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002245 err_code |= ERR_ALERT | ERR_FATAL;
2246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002248
Willy Tarreau67402132012-05-31 20:40:20 +02002249 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002250 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002251 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002252 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 curproxy->cookie_name = strdup(args[1]);
2254 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 cur_arg = 2;
2257 while (*(args[cur_arg])) {
2258 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002259 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
2261 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002262 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 }
2264 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002265 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 }
2267 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002268 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 }
2270 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002271 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002273 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002274 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002277 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002279 else if (!strcmp(args[cur_arg], "httponly")) {
2280 curproxy->ck_opts |= PR_CK_HTTPONLY;
2281 }
2282 else if (!strcmp(args[cur_arg], "secure")) {
2283 curproxy->ck_opts |= PR_CK_SECURE;
2284 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002285 else if (!strcmp(args[cur_arg], "domain")) {
2286 if (!*args[cur_arg + 1]) {
2287 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2288 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002291 }
2292
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002293 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002294 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002295 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2296 " dots nor does not start with a dot."
2297 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002298 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002299 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002300 }
2301
2302 err = invalid_domainchar(args[cur_arg + 1]);
2303 if (err) {
2304 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2305 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002308 }
2309
Willy Tarreau68a897b2009-12-03 23:28:34 +01002310 if (!curproxy->cookie_domain) {
2311 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2312 } else {
2313 /* one domain was already specified, add another one by
2314 * building the string which will be returned along with
2315 * the cookie.
2316 */
2317 char *new_ptr;
2318 int new_len = strlen(curproxy->cookie_domain) +
2319 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2320 new_ptr = malloc(new_len);
2321 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2322 free(curproxy->cookie_domain);
2323 curproxy->cookie_domain = new_ptr;
2324 }
Willy Tarreau31936852010-10-06 16:59:56 +02002325 cur_arg++;
2326 }
2327 else if (!strcmp(args[cur_arg], "maxidle")) {
2328 unsigned int maxidle;
2329 const char *res;
2330
2331 if (!*args[cur_arg + 1]) {
2332 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2333 file, linenum, args[cur_arg]);
2334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
2336 }
2337
2338 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2339 if (res) {
2340 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2341 file, linenum, *res, args[cur_arg]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345 curproxy->cookie_maxidle = maxidle;
2346 cur_arg++;
2347 }
2348 else if (!strcmp(args[cur_arg], "maxlife")) {
2349 unsigned int maxlife;
2350 const char *res;
2351
2352 if (!*args[cur_arg + 1]) {
2353 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2354 file, linenum, args[cur_arg]);
2355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
2357 }
2358
2359 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2360 if (res) {
2361 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2362 file, linenum, *res, args[cur_arg]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002367 cur_arg++;
2368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002370 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 +02002371 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002372 err_code |= ERR_ALERT | ERR_FATAL;
2373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 }
2375 cur_arg++;
2376 }
Willy Tarreau67402132012-05-31 20:40:20 +02002377 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2379 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 }
2382
Willy Tarreau67402132012-05-31 20:40:20 +02002383 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002388
Willy Tarreau67402132012-05-31 20:40:20 +02002389 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002390 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2391 file, linenum);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002395 else if (!strcmp(args[0], "persist")) { /* persist */
2396 if (*(args[1]) == 0) {
2397 Alert("parsing [%s:%d] : missing persist method.\n",
2398 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002401 }
2402
2403 if (!strncmp(args[1], "rdp-cookie", 10)) {
2404 curproxy->options2 |= PR_O2_RDPC_PRST;
2405
Emeric Brunb982a3d2010-01-04 15:45:53 +01002406 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002407 const char *beg, *end;
2408
2409 beg = args[1] + 11;
2410 end = strchr(beg, ')');
2411
2412 if (!end || end == beg) {
2413 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2414 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002417 }
2418
2419 free(curproxy->rdp_cookie_name);
2420 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2421 curproxy->rdp_cookie_len = end-beg;
2422 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002423 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002424 free(curproxy->rdp_cookie_name);
2425 curproxy->rdp_cookie_name = strdup("msts");
2426 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2427 }
2428 else { /* syntax */
2429 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2430 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002433 }
2434 }
2435 else {
2436 Alert("parsing [%s:%d] : unknown persist method.\n",
2437 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002440 }
2441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002443 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002445 if (curproxy == &defproxy) {
2446 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002453
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002455 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
2460 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002461 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 curproxy->appsession_name = strdup(args[1]);
2463 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2464 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002465 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2466 if (err) {
2467 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2468 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002471 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002472 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002473
Willy Tarreau51041c72007-09-09 21:56:53 +02002474 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2475 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_ABORT;
2477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002479
2480 cur_arg = 6;
2481 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002482 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2483 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002484 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002485 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002486 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002487 } else if (!strcmp(args[cur_arg], "prefix")) {
2488 curproxy->options2 |= PR_O2_AS_PFX;
2489 } else if (!strcmp(args[cur_arg], "mode")) {
2490 if (!*args[cur_arg + 1]) {
2491 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2492 file, linenum, args[0], args[cur_arg]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
2497 cur_arg++;
2498 if (!strcmp(args[cur_arg], "query-string")) {
2499 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2500 curproxy->options2 |= PR_O2_AS_M_QS;
2501 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2502 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2503 curproxy->options2 |= PR_O2_AS_M_PP;
2504 } else {
2505 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
2508 }
2509 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002510 cur_arg++;
2511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 } /* Url App Session */
2513 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002514 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002516
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002518 if (curproxy == &defproxy) {
2519 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
2522 }
2523
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 if (*(args[4]) == 0) {
2525 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2526 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002530 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002531 curproxy->capture_name = strdup(args[2]);
2532 curproxy->capture_namelen = strlen(curproxy->capture_name);
2533 curproxy->capture_len = atol(args[4]);
2534 if (curproxy->capture_len >= CAPTURE_LEN) {
2535 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2536 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002538 curproxy->capture_len = CAPTURE_LEN - 1;
2539 }
2540 curproxy->to_log |= LW_COOKIE;
2541 }
2542 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2543 struct cap_hdr *hdr;
2544
2545 if (curproxy == &defproxy) {
2546 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 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }
2550
2551 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2552 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2553 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 }
2557
2558 hdr = calloc(sizeof(struct cap_hdr), 1);
2559 hdr->next = curproxy->req_cap;
2560 hdr->name = strdup(args[3]);
2561 hdr->namelen = strlen(args[3]);
2562 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002563 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 hdr->index = curproxy->nb_req_cap++;
2565 curproxy->req_cap = hdr;
2566 curproxy->to_log |= LW_REQHDR;
2567 }
2568 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2569 struct cap_hdr *hdr;
2570
2571 if (curproxy == &defproxy) {
2572 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 +02002573 err_code |= ERR_ALERT | ERR_FATAL;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
2576
2577 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2578 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2579 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
2583 hdr = calloc(sizeof(struct cap_hdr), 1);
2584 hdr->next = curproxy->rsp_cap;
2585 hdr->name = strdup(args[3]);
2586 hdr->namelen = strlen(args[3]);
2587 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002588 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 hdr->index = curproxy->nb_rsp_cap++;
2590 curproxy->rsp_cap = hdr;
2591 curproxy->to_log |= LW_RSPHDR;
2592 }
2593 else {
2594 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
2599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002603
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 if (*(args[1]) == 0) {
2605 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2606 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 }
2610 curproxy->conn_retries = atol(args[1]);
2611 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002612 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002613 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002614
2615 if (curproxy == &defproxy) {
2616 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
2619 }
2620
Willy Tarreauff011f22011-01-06 17:51:27 +01002621 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 +01002622 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2623 file, linenum, args[0]);
2624 err_code |= ERR_WARN;
2625 }
2626
Willy Tarreauff011f22011-01-06 17:51:27 +01002627 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002628
Willy Tarreauff011f22011-01-06 17:51:27 +01002629 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002630 err_code |= ERR_ALERT | ERR_ABORT;
2631 goto out;
2632 }
2633
Willy Tarreauff011f22011-01-06 17:51:27 +01002634 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2635 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002636 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002637 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2638 /* set the header name and length into the proxy structure */
2639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2640 err_code |= ERR_WARN;
2641
2642 if (!*args[1]) {
2643 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2644 file, linenum, args[0]);
2645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
2647 }
2648
2649 /* set the desired header name */
2650 free(curproxy->server_id_hdr_name);
2651 curproxy->server_id_hdr_name = strdup(args[1]);
2652 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2653 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002654 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002655 if (curproxy == &defproxy) {
2656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002659 }
2660
Willy Tarreauef6494c2010-01-28 17:12:36 +01002661 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002662 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2663 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002666 }
2667
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002668 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2669 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2670 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002673 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002674
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002675 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002676 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002677 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 struct redirect_rule *rule;
2680 int cur_arg;
2681 int type = REDIRECT_TYPE_NONE;
2682 int code = 302;
2683 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002684 char *cookie = NULL;
2685 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002686 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002687
Cyril Bonté99ed3272010-01-24 23:29:44 +01002688 if (curproxy == &defproxy) {
2689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002694 cur_arg = 1;
2695 while (*(args[cur_arg])) {
2696 if (!strcmp(args[cur_arg], "location")) {
2697 if (!*args[cur_arg + 1]) {
2698 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2699 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002702 }
2703
2704 type = REDIRECT_TYPE_LOCATION;
2705 cur_arg++;
2706 destination = args[cur_arg];
2707 }
2708 else if (!strcmp(args[cur_arg], "prefix")) {
2709 if (!*args[cur_arg + 1]) {
2710 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2711 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002714 }
2715
2716 type = REDIRECT_TYPE_PREFIX;
2717 cur_arg++;
2718 destination = args[cur_arg];
2719 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002720 else if (!strcmp(args[cur_arg], "set-cookie")) {
2721 if (!*args[cur_arg + 1]) {
2722 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2723 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002726 }
2727
2728 cur_arg++;
2729 cookie = args[cur_arg];
2730 cookie_set = 1;
2731 }
2732 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2733 if (!*args[cur_arg + 1]) {
2734 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2735 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002738 }
2739
2740 cur_arg++;
2741 cookie = args[cur_arg];
2742 cookie_set = 0;
2743 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002744 else if (!strcmp(args[cur_arg],"code")) {
2745 if (!*args[cur_arg + 1]) {
2746 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002750 }
2751 cur_arg++;
2752 code = atol(args[cur_arg]);
2753 if (code < 301 || code > 303) {
2754 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2755 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002758 }
2759 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002760 else if (!strcmp(args[cur_arg],"drop-query")) {
2761 flags |= REDIRECT_FLAG_DROP_QS;
2762 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002763 else if (!strcmp(args[cur_arg],"append-slash")) {
2764 flags |= REDIRECT_FLAG_APPEND_SLASH;
2765 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002766 else if (strcmp(args[cur_arg], "if") == 0 ||
2767 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002768 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002769 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002770 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2771 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
2774 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002775 break;
2776 }
2777 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002778 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 +02002779 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002782 }
2783 cur_arg++;
2784 }
2785
2786 if (type == REDIRECT_TYPE_NONE) {
2787 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2788 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002791 }
2792
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002793 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2794 rule->cond = cond;
2795 rule->rdr_str = strdup(destination);
2796 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002797 if (cookie) {
2798 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002799 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002800 */
2801 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002802 if (cookie_set) {
2803 rule->cookie_str = malloc(rule->cookie_len + 10);
2804 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2805 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2806 rule->cookie_len += 9;
2807 } else {
2808 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002809 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002810 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2811 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002812 }
2813 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002814 rule->type = type;
2815 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002816 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002817 LIST_INIT(&rule->list);
2818 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002819 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2820 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002821 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002822 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002823 struct switching_rule *rule;
2824
Willy Tarreaub099aca2008-10-12 17:26:37 +02002825 if (curproxy == &defproxy) {
2826 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002829 }
2830
Willy Tarreau55ea7572007-06-17 19:56:27 +02002831 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002832 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002833
2834 if (*(args[1]) == 0) {
2835 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002838 }
2839
Willy Tarreauef6494c2010-01-28 17:12:36 +01002840 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002841 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002845 }
2846
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002847 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2848 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2849 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002852 }
2853
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002854 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002855
Willy Tarreau55ea7572007-06-17 19:56:27 +02002856 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2857 rule->cond = cond;
2858 rule->be.name = strdup(args[1]);
2859 LIST_INIT(&rule->list);
2860 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2861 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002862 else if (strcmp(args[0], "use-server") == 0) {
2863 struct server_rule *rule;
2864
2865 if (curproxy == &defproxy) {
2866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870
2871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2872 err_code |= ERR_WARN;
2873
2874 if (*(args[1]) == 0) {
2875 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879
2880 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2881 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2882 file, linenum, args[0]);
2883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
2885 }
2886
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2888 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2889 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
2893
2894 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2895
2896 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2897 rule->cond = cond;
2898 rule->srv.name = strdup(args[1]);
2899 LIST_INIT(&rule->list);
2900 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2901 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2902 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002903 else if ((!strcmp(args[0], "force-persist")) ||
2904 (!strcmp(args[0], "ignore-persist"))) {
2905 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002906
2907 if (curproxy == &defproxy) {
2908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
2913 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2914 err_code |= ERR_WARN;
2915
Willy Tarreauef6494c2010-01-28 17:12:36 +01002916 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002917 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2918 file, linenum, args[0]);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002923 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2924 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2925 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002930 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002931
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002932 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002933 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002934 if (!strcmp(args[0], "force-persist")) {
2935 rule->type = PERSIST_TYPE_FORCE;
2936 } else {
2937 rule->type = PERSIST_TYPE_IGNORE;
2938 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002939 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002940 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002941 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002942 else if (!strcmp(args[0], "stick-table")) {
2943 int myidx = 1;
2944
Emeric Brun32da3c42010-09-23 18:39:19 +02002945 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002946 curproxy->table.type = (unsigned int)-1;
2947 while (*args[myidx]) {
2948 const char *err;
2949
2950 if (strcmp(args[myidx], "size") == 0) {
2951 myidx++;
2952 if (!*(args[myidx])) {
2953 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2954 file, linenum, args[myidx-1]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
2958 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2959 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2960 file, linenum, *err, args[myidx-1]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002964 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002965 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002966 else if (strcmp(args[myidx], "peers") == 0) {
2967 myidx++;
2968 if (!*(args[myidx])) {
2969 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2970 file, linenum, args[myidx-1]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974 curproxy->table.peers.name = strdup(args[myidx++]);
2975 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 else if (strcmp(args[myidx], "expire") == 0) {
2977 myidx++;
2978 if (!*(args[myidx])) {
2979 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2980 file, linenum, args[myidx-1]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2985 if (err) {
2986 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2987 file, linenum, *err, args[myidx-1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002992 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002993 }
2994 else if (strcmp(args[myidx], "nopurge") == 0) {
2995 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002996 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002997 }
2998 else if (strcmp(args[myidx], "type") == 0) {
2999 myidx++;
3000 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3001 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3002 file, linenum, args[myidx]);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003006 /* myidx already points to next arg */
3007 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003008 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003009 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003010 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003011
3012 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003013 nw = args[myidx];
3014 while (*nw) {
3015 /* the "store" keyword supports a comma-separated list */
3016 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003017 sa = NULL; /* store arg */
3018 while (*nw && *nw != ',') {
3019 if (*nw == '(') {
3020 *nw = 0;
3021 sa = ++nw;
3022 while (*nw != ')') {
3023 if (!*nw) {
3024 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3025 file, linenum, args[0], cw);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029 nw++;
3030 }
3031 *nw = '\0';
3032 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003033 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003034 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003035 if (*nw)
3036 *nw++ = '\0';
3037 type = stktable_get_data_type(cw);
3038 if (type < 0) {
3039 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3040 file, linenum, args[0], cw);
3041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
3043 }
Willy Tarreauac782882010-06-20 10:41:54 +02003044
3045 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3046 switch (err) {
3047 case PE_NONE: break;
3048 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003049 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3050 file, linenum, args[0], cw);
3051 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003052 break;
3053
3054 case PE_ARG_MISSING:
3055 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3056 file, linenum, args[0], cw);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059
3060 case PE_ARG_NOT_USED:
3061 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3062 file, linenum, args[0], cw);
3063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
3065
3066 default:
3067 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3068 file, linenum, args[0], cw);
3069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003071 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003072 }
3073 myidx++;
3074 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003075 else {
3076 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3077 file, linenum, args[myidx]);
3078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003081 }
3082
3083 if (!curproxy->table.size) {
3084 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3085 file, linenum);
3086 err_code |= ERR_ALERT | ERR_FATAL;
3087 goto out;
3088 }
3089
3090 if (curproxy->table.type == (unsigned int)-1) {
3091 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3092 file, linenum);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096 }
3097 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003098 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003099 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003100 int myidx = 0;
3101 const char *name = NULL;
3102 int flags;
3103
3104 if (curproxy == &defproxy) {
3105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
3108 }
3109
3110 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3111 err_code |= ERR_WARN;
3112 goto out;
3113 }
3114
3115 myidx++;
3116 if ((strcmp(args[myidx], "store") == 0) ||
3117 (strcmp(args[myidx], "store-request") == 0)) {
3118 myidx++;
3119 flags = STK_IS_STORE;
3120 }
3121 else if (strcmp(args[myidx], "store-response") == 0) {
3122 myidx++;
3123 flags = STK_IS_STORE | STK_ON_RSP;
3124 }
3125 else if (strcmp(args[myidx], "match") == 0) {
3126 myidx++;
3127 flags = STK_IS_MATCH;
3128 }
3129 else if (strcmp(args[myidx], "on") == 0) {
3130 myidx++;
3131 flags = STK_IS_MATCH | STK_IS_STORE;
3132 }
3133 else {
3134 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
3139 if (*(args[myidx]) == 0) {
3140 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
3143 }
3144
David du Colombier7af46052012-05-16 14:16:48 +02003145 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003146 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003147 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
3152 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003153 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3155 file, linenum, args[0], expr->fetch->kw);
3156 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003157 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003158 goto out;
3159 }
3160 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003161 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3163 file, linenum, args[0], expr->fetch->kw);
3164 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003165 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 goto out;
3167 }
3168 }
3169
3170 if (strcmp(args[myidx], "table") == 0) {
3171 myidx++;
3172 name = args[myidx++];
3173 }
3174
Willy Tarreauef6494c2010-01-28 17:12:36 +01003175 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003176 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3177 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3178 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003179 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003180 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 goto out;
3182 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003183 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003184 else if (*(args[myidx])) {
3185 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3186 file, linenum, args[0], args[myidx]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003188 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003189 goto out;
3190 }
Emeric Brun97679e72010-09-23 17:56:44 +02003191 if (flags & STK_ON_RSP)
3192 err_code |= warnif_cond_requires_req(cond, file, linenum);
3193 else
3194 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003195
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3197 rule->cond = cond;
3198 rule->expr = expr;
3199 rule->flags = flags;
3200 rule->table.name = name ? strdup(name) : NULL;
3201 LIST_INIT(&rule->list);
3202 if (flags & STK_ON_RSP)
3203 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3204 else
3205 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003208 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003210
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3212 curproxy->uri_auth = NULL; /* we must detach from the default config */
3213
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003214 if (!*args[1]) {
3215 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003216 } else if (!strcmp(args[1], "admin")) {
3217 struct stats_admin_rule *rule;
3218
3219 if (curproxy == &defproxy) {
3220 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3221 err_code |= ERR_ALERT | ERR_FATAL;
3222 goto out;
3223 }
3224
3225 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3226 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3227 err_code |= ERR_ALERT | ERR_ABORT;
3228 goto out;
3229 }
3230
3231 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3232 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3233 file, linenum, args[0], args[1]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003237 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3238 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3239 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
3242 }
3243
3244 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3245
3246 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3247 rule->cond = cond;
3248 LIST_INIT(&rule->list);
3249 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 } else if (!strcmp(args[1], "uri")) {
3251 if (*(args[2]) == 0) {
3252 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3256 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_ABORT;
3258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
3260 } else if (!strcmp(args[1], "realm")) {
3261 if (*(args[2]) == 0) {
3262 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003263 err_code |= ERR_ALERT | ERR_FATAL;
3264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3266 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_ABORT;
3268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003270 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003271 unsigned interval;
3272
3273 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3274 if (err) {
3275 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3276 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003279 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3280 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_ALERT | ERR_ABORT;
3282 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003283 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003284 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003285 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003286
3287 if (curproxy == &defproxy) {
3288 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292
3293 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3294 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3295 err_code |= ERR_ALERT | ERR_ABORT;
3296 goto out;
3297 }
3298
Willy Tarreauff011f22011-01-06 17:51:27 +01003299 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3300 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003301 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3302 file, linenum, args[0]);
3303 err_code |= ERR_WARN;
3304 }
3305
Willy Tarreauff011f22011-01-06 17:51:27 +01003306 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003307
Willy Tarreauff011f22011-01-06 17:51:27 +01003308 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003309 err_code |= ERR_ALERT | ERR_ABORT;
3310 goto out;
3311 }
3312
Willy Tarreauff011f22011-01-06 17:51:27 +01003313 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3314 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003315
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 } else if (!strcmp(args[1], "auth")) {
3317 if (*(args[2]) == 0) {
3318 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3322 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_ALERT | ERR_ABORT;
3324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 }
3326 } else if (!strcmp(args[1], "scope")) {
3327 if (*(args[2]) == 0) {
3328 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3332 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003333 err_code |= ERR_ALERT | ERR_ABORT;
3334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 }
3336 } else if (!strcmp(args[1], "enable")) {
3337 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3338 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_ABORT;
3340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003342 } else if (!strcmp(args[1], "hide-version")) {
3343 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3344 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_ABORT;
3346 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003347 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003348 } else if (!strcmp(args[1], "show-legends")) {
3349 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3350 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3351 err_code |= ERR_ALERT | ERR_ABORT;
3352 goto out;
3353 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003354 } else if (!strcmp(args[1], "show-node")) {
3355
3356 if (*args[2]) {
3357 int i;
3358 char c;
3359
3360 for (i=0; args[2][i]; i++) {
3361 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003362 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3363 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003364 break;
3365 }
3366
3367 if (!i || args[2][i]) {
3368 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3369 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3370 file, linenum, args[0], args[1]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374 }
3375
3376 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3377 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3378 err_code |= ERR_ALERT | ERR_ABORT;
3379 goto out;
3380 }
3381 } else if (!strcmp(args[1], "show-desc")) {
3382 char *desc = NULL;
3383
3384 if (*args[2]) {
3385 int i, len=0;
3386 char *d;
3387
3388 for(i=2; *args[i]; i++)
3389 len += strlen(args[i])+1;
3390
3391 desc = d = (char *)calloc(1, len);
3392
3393 d += sprintf(d, "%s", args[2]);
3394 for(i=3; *args[i]; i++)
3395 d += sprintf(d, " %s", args[i]);
3396 }
3397
3398 if (!*args[2] && !global.desc)
3399 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3400 file, linenum, args[1]);
3401 else {
3402 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3403 free(desc);
3404 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3405 err_code |= ERR_ALERT | ERR_ABORT;
3406 goto out;
3407 }
3408 free(desc);
3409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003411stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003412 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 +01003413 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 }
3417 }
3418 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003419 int optnum;
3420
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003421 if (*(args[1]) == '\0') {
3422 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003427
3428 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3429 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003430 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3431 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3432 file, linenum, cfg_opts[optnum].name);
3433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
Willy Tarreau93893792009-07-23 13:19:11 +02003436 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3437 err_code |= ERR_WARN;
3438 goto out;
3439 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003440
Willy Tarreau3842f002009-06-14 11:39:52 +02003441 curproxy->no_options &= ~cfg_opts[optnum].val;
3442 curproxy->options &= ~cfg_opts[optnum].val;
3443
3444 switch (kwm) {
3445 case KWM_STD:
3446 curproxy->options |= cfg_opts[optnum].val;
3447 break;
3448 case KWM_NO:
3449 curproxy->no_options |= cfg_opts[optnum].val;
3450 break;
3451 case KWM_DEF: /* already cleared */
3452 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003453 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003454
Willy Tarreau93893792009-07-23 13:19:11 +02003455 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003456 }
3457 }
3458
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003459 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3460 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003461 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3462 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3463 file, linenum, cfg_opts2[optnum].name);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
Willy Tarreau93893792009-07-23 13:19:11 +02003467 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3468 err_code |= ERR_WARN;
3469 goto out;
3470 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003471
Willy Tarreau3842f002009-06-14 11:39:52 +02003472 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3473 curproxy->options2 &= ~cfg_opts2[optnum].val;
3474
3475 switch (kwm) {
3476 case KWM_STD:
3477 curproxy->options2 |= cfg_opts2[optnum].val;
3478 break;
3479 case KWM_NO:
3480 curproxy->no_options2 |= cfg_opts2[optnum].val;
3481 break;
3482 case KWM_DEF: /* already cleared */
3483 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003484 }
Willy Tarreau93893792009-07-23 13:19:11 +02003485 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003486 }
3487 }
3488
Willy Tarreau3842f002009-06-14 11:39:52 +02003489 if (kwm != KWM_STD) {
3490 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003491 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003494 }
3495
Emeric Brun3a058f32009-06-30 18:26:00 +02003496 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003497 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003499 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003500 if (*(args[2]) != '\0') {
3501 if (!strcmp(args[2], "clf")) {
3502 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003503 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003504 } else {
3505 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003508 }
3509 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003510 if (curproxy->logformat_string != default_http_log_format &&
3511 curproxy->logformat_string != default_tcp_log_format &&
3512 curproxy->logformat_string != clf_http_log_format)
3513 free(curproxy->logformat_string);
3514 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003515 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003516 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003518 if (curproxy->logformat_string != default_http_log_format &&
3519 curproxy->logformat_string != default_tcp_log_format &&
3520 curproxy->logformat_string != clf_http_log_format)
3521 free(curproxy->logformat_string);
3522 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 else if (!strcmp(args[1], "tcpka")) {
3525 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003526 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003528
3529 if (curproxy->cap & PR_CAP_FE)
3530 curproxy->options |= PR_O_TCP_CLI_KA;
3531 if (curproxy->cap & PR_CAP_BE)
3532 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 }
3534 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003535 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_WARN;
3537
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003539 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003540 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003541 curproxy->options2 &= ~PR_O2_CHK_ANY;
3542 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003543 if (!*args[2]) { /* no argument */
3544 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3545 curproxy->check_len = strlen(DEF_CHECK_REQ);
3546 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003547 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 curproxy->check_req = (char *)malloc(reqlen);
3549 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003550 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003552 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 if (*args[4])
3554 reqlen += strlen(args[4]);
3555 else
3556 reqlen += strlen("HTTP/1.0");
3557
3558 curproxy->check_req = (char *)malloc(reqlen);
3559 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003560 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003562 }
3563 else if (!strcmp(args[1], "ssl-hello-chk")) {
3564 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003567
Willy Tarreaua534fea2008-08-03 12:19:50 +02003568 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003569 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003570 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003571 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
Willy Tarreau23677902007-05-08 23:50:35 +02003573 else if (!strcmp(args[1], "smtpchk")) {
3574 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003575 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003576 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003577 curproxy->options2 &= ~PR_O2_CHK_ANY;
3578 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003579
3580 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3581 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3582 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3583 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3584 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3585 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3586 curproxy->check_req = (char *)malloc(reqlen);
3587 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3588 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3589 } else {
3590 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3591 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3592 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3593 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3594 }
3595 }
3596 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003597 else if (!strcmp(args[1], "pgsql-check")) {
3598 /* use PostgreSQL request to check servers' health */
3599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3600 err_code |= ERR_WARN;
3601
3602 free(curproxy->check_req);
3603 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003604 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003605 curproxy->options2 |= PR_O2_PGSQL_CHK;
3606
3607 if (*(args[2])) {
3608 int cur_arg = 2;
3609
3610 while (*(args[cur_arg])) {
3611 if (strcmp(args[cur_arg], "user") == 0) {
3612 char * packet;
3613 uint32_t packet_len;
3614 uint32_t pv;
3615
3616 /* suboption header - needs additional argument for it */
3617 if (*(args[cur_arg+1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3619 file, linenum, args[0], args[1], args[cur_arg]);
3620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
3622 }
3623
3624 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3625 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3626 pv = htonl(0x30000); /* protocol version 3.0 */
3627
3628 packet = (char*) calloc(1, packet_len);
3629
3630 memcpy(packet + 4, &pv, 4);
3631
3632 /* copy "user" */
3633 memcpy(packet + 8, "user", 4);
3634
3635 /* copy username */
3636 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3637
3638 free(curproxy->check_req);
3639 curproxy->check_req = packet;
3640 curproxy->check_len = packet_len;
3641
3642 packet_len = htonl(packet_len);
3643 memcpy(packet, &packet_len, 4);
3644 cur_arg += 2;
3645 } else {
3646 /* unknown suboption - catchall */
3647 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3648 file, linenum, args[0], args[1]);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
3652 } /* end while loop */
3653 }
3654 }
3655
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003656 else if (!strcmp(args[1], "redis-check")) {
3657 /* use REDIS PING request to check servers' health */
3658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3659 err_code |= ERR_WARN;
3660
3661 free(curproxy->check_req);
3662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003663 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003664 curproxy->options2 |= PR_O2_REDIS_CHK;
3665
3666 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3667 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3668 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3669 }
3670
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003671 else if (!strcmp(args[1], "mysql-check")) {
3672 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003673 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3674 err_code |= ERR_WARN;
3675
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003676 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003677 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003678 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003679 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003680
3681 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3682 * const char mysql40_client_auth_pkt[] = {
3683 * "\x0e\x00\x00" // packet length
3684 * "\x01" // packet number
3685 * "\x00\x00" // client capabilities
3686 * "\x00\x00\x01" // max packet
3687 * "haproxy\x00" // username (null terminated string)
3688 * "\x00" // filler (always 0x00)
3689 * "\x01\x00\x00" // packet length
3690 * "\x00" // packet number
3691 * "\x01" // COM_QUIT command
3692 * };
3693 */
3694
3695 if (*(args[2])) {
3696 int cur_arg = 2;
3697
3698 while (*(args[cur_arg])) {
3699 if (strcmp(args[cur_arg], "user") == 0) {
3700 char *mysqluser;
3701 int packetlen, reqlen, userlen;
3702
3703 /* suboption header - needs additional argument for it */
3704 if (*(args[cur_arg+1]) == 0) {
3705 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3706 file, linenum, args[0], args[1], args[cur_arg]);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710 mysqluser = args[cur_arg + 1];
3711 userlen = strlen(mysqluser);
3712 packetlen = userlen + 7;
3713 reqlen = packetlen + 9;
3714
3715 free(curproxy->check_req);
3716 curproxy->check_req = (char *)calloc(1, reqlen);
3717 curproxy->check_len = reqlen;
3718
3719 snprintf(curproxy->check_req, 4, "%c%c%c",
3720 ((unsigned char) packetlen & 0xff),
3721 ((unsigned char) (packetlen >> 8) & 0xff),
3722 ((unsigned char) (packetlen >> 16) & 0xff));
3723
3724 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003725 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003726 curproxy->check_req[8] = 1;
3727 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3728 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3729 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3730 cur_arg += 2;
3731 } else {
3732 /* unknown suboption - catchall */
3733 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3734 file, linenum, args[0], args[1]);
3735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
3737 }
3738 } /* end while loop */
3739 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003740 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003741 else if (!strcmp(args[1], "ldap-check")) {
3742 /* use LDAP request to check servers' health */
3743 free(curproxy->check_req);
3744 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003745 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003746 curproxy->options2 |= PR_O2_LDAP_CHK;
3747
3748 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3749 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3750 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3751 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003752 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003753 int cur_arg;
3754
3755 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3756 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003757 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003758
Willy Tarreau87cf5142011-08-19 22:57:24 +02003759 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003760
3761 free(curproxy->fwdfor_hdr_name);
3762 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3763 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3764
3765 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3766 cur_arg = 2;
3767 while (*(args[cur_arg])) {
3768 if (!strcmp(args[cur_arg], "except")) {
3769 /* suboption except - needs additional argument for it */
3770 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3771 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3772 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003775 }
3776 /* flush useless bits */
3777 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003778 cur_arg += 2;
3779 } else if (!strcmp(args[cur_arg], "header")) {
3780 /* suboption header - needs additional argument for it */
3781 if (*(args[cur_arg+1]) == 0) {
3782 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3783 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003786 }
3787 free(curproxy->fwdfor_hdr_name);
3788 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3789 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3790 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003791 } else if (!strcmp(args[cur_arg], "if-none")) {
3792 curproxy->options &= ~PR_O_FF_ALWAYS;
3793 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003794 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003795 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003796 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003797 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003800 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003801 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003802 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003803 else if (!strcmp(args[1], "originalto")) {
3804 int cur_arg;
3805
3806 /* insert x-original-to field, but not for the IP address listed as an except.
3807 * set default options (ie: bitfield, header name, etc)
3808 */
3809
3810 curproxy->options |= PR_O_ORGTO;
3811
3812 free(curproxy->orgto_hdr_name);
3813 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3814 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3815
Willy Tarreau87cf5142011-08-19 22:57:24 +02003816 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003817 cur_arg = 2;
3818 while (*(args[cur_arg])) {
3819 if (!strcmp(args[cur_arg], "except")) {
3820 /* suboption except - needs additional argument for it */
3821 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3822 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3823 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003826 }
3827 /* flush useless bits */
3828 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3829 cur_arg += 2;
3830 } else if (!strcmp(args[cur_arg], "header")) {
3831 /* suboption header - needs additional argument for it */
3832 if (*(args[cur_arg+1]) == 0) {
3833 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3834 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003837 }
3838 free(curproxy->orgto_hdr_name);
3839 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3840 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3841 cur_arg += 2;
3842 } else {
3843 /* unknown suboption - catchall */
3844 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3845 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003848 }
3849 } /* end while loop */
3850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 else {
3852 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 }
Willy Tarreau93893792009-07-23 13:19:11 +02003856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003858 else if (!strcmp(args[0], "default_backend")) {
3859 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003861
3862 if (*(args[1]) == 0) {
3863 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003866 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003867 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003868 curproxy->defbe.name = strdup(args[1]);
3869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003873
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003874 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003876 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 /* enable reconnections to dispatch */
3878 curproxy->options |= PR_O_REDISP;
3879 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003880 else if (!strcmp(args[0], "http-check")) {
3881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003883
3884 if (strcmp(args[1], "disable-on-404") == 0) {
3885 /* enable a graceful server shutdown on an HTTP 404 response */
3886 curproxy->options |= PR_O_DISABLE404;
3887 }
Willy Tarreauef781042010-01-27 11:53:01 +01003888 else if (strcmp(args[1], "send-state") == 0) {
3889 /* enable emission of the apparent state of a server in HTTP checks */
3890 curproxy->options2 |= PR_O2_CHK_SNDST;
3891 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003892 else if (strcmp(args[1], "expect") == 0) {
3893 const char *ptr_arg;
3894 int cur_arg;
3895
3896 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3897 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
3900 }
3901
3902 cur_arg = 2;
3903 /* consider exclamation marks, sole or at the beginning of a word */
3904 while (*(ptr_arg = args[cur_arg])) {
3905 while (*ptr_arg == '!') {
3906 curproxy->options2 ^= PR_O2_EXP_INV;
3907 ptr_arg++;
3908 }
3909 if (*ptr_arg)
3910 break;
3911 cur_arg++;
3912 }
3913 /* now ptr_arg points to the beginning of a word past any possible
3914 * exclamation mark, and cur_arg is the argument which holds this word.
3915 */
3916 if (strcmp(ptr_arg, "status") == 0) {
3917 if (!*(args[cur_arg + 1])) {
3918 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3919 file, linenum, args[0], args[1], ptr_arg);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003924 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003925 curproxy->expect_str = strdup(args[cur_arg + 1]);
3926 }
3927 else if (strcmp(ptr_arg, "string") == 0) {
3928 if (!*(args[cur_arg + 1])) {
3929 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3930 file, linenum, args[0], args[1], ptr_arg);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003935 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003936 curproxy->expect_str = strdup(args[cur_arg + 1]);
3937 }
3938 else if (strcmp(ptr_arg, "rstatus") == 0) {
3939 if (!*(args[cur_arg + 1])) {
3940 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3941 file, linenum, args[0], args[1], ptr_arg);
3942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
3944 }
3945 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003946 free(curproxy->expect_str);
3947 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3948 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003949 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3950 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3951 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3952 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 }
3957 else if (strcmp(ptr_arg, "rstring") == 0) {
3958 if (!*(args[cur_arg + 1])) {
3959 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3960 file, linenum, args[0], args[1], ptr_arg);
3961 err_code |= ERR_ALERT | ERR_FATAL;
3962 goto out;
3963 }
3964 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003965 free(curproxy->expect_str);
3966 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3967 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003968 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3969 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3970 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3971 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
3973 goto out;
3974 }
3975 }
3976 else {
3977 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3978 file, linenum, args[0], args[1], ptr_arg);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003983 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003984 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 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003987 }
3988 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003989 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003990 if (curproxy == &defproxy) {
3991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003994 }
3995
Willy Tarreaub80c2302007-11-30 20:51:32 +01003996 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003998
3999 if (strcmp(args[1], "fail") == 0) {
4000 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004001 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004002 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4003 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004006 }
4007
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004008 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4009 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4010 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004013 }
4014 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4015 }
4016 else {
4017 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004020 }
4021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022#ifdef TPROXY
4023 else if (!strcmp(args[0], "transparent")) {
4024 /* enable transparent proxy connections */
4025 curproxy->options |= PR_O_TRANSP;
4026 }
4027#endif
4028 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004029 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004031
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 if (*(args[1]) == 0) {
4033 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 }
4037 curproxy->maxconn = atol(args[1]);
4038 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004039 else if (!strcmp(args[0], "backlog")) { /* backlog */
4040 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004041 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004042
4043 if (*(args[1]) == 0) {
4044 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004047 }
4048 curproxy->backlog = atol(args[1]);
4049 }
Willy Tarreau86034312006-12-29 00:10:33 +01004050 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004051 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004052 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004053
Willy Tarreau86034312006-12-29 00:10:33 +01004054 if (*(args[1]) == 0) {
4055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004058 }
4059 curproxy->fullconn = atol(args[1]);
4060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004061 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4062 if (*(args[1]) == 0) {
4063 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004067 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4068 if (err) {
4069 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4070 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004073 }
4074 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 }
4076 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004077 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 if (curproxy == &defproxy) {
4079 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004082 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004083 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 if (strchr(args[1], ':') == NULL) {
4087 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004091 sk = str2sa(args[1]);
4092 if (!sk) {
4093 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004098 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 }
4100 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004101 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004102 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004103
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004104 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4105 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004109 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004110 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4111 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4112 err_code |= ERR_WARN;
4113
4114 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4115 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4116 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4117 }
4118 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4119 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4120 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4121 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004122 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4123 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4124 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4125 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004126 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004127 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004132 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004134 char *rport, *raddr;
4135 short realport = 0;
4136 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004143 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145
4146 if (!*args[2]) {
4147 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004152
4153 err = invalid_char(args[1]);
4154 if (err) {
4155 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4156 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004159 }
4160
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004161 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004162 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004163
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004164 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4166 err_code |= ERR_ALERT | ERR_ABORT;
4167 goto out;
4168 }
4169
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004170 /* the servers are linked backwards first */
4171 newsrv->next = curproxy->srv;
4172 curproxy->srv = newsrv;
4173 newsrv->proxy = curproxy;
4174 newsrv->conf.file = file;
4175 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176
Simon Hormanaf514952011-06-21 14:34:57 +09004177 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004178 LIST_INIT(&newsrv->pendconns);
4179 do_check = 0;
4180 newsrv->state = SRV_RUNNING; /* early server setup */
4181 newsrv->last_change = now.tv_sec;
4182 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004184 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004185 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186 * - IP: => port=+0, relative
4187 * - IP:N => port=N, absolute
4188 * - IP:+N => port=+N, relative
4189 * - IP:-N => port=-N, relative
4190 */
4191 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004192 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004193 if (rport) {
4194 *rport++ = 0;
4195 realport = atol(rport);
4196 if (!isdigit((unsigned char)*rport))
4197 newsrv->state |= SRV_MAPPORTS;
4198 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004200
Willy Tarreaufab5a432011-03-04 15:31:53 +01004201 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004202 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004203 if (!sk) {
4204 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
4207 }
4208 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004209 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004210 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004211
4212 if (!sk) {
4213 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4214 file, linenum, newsrv->addr.ss_family, args[2]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004218 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004219
4220 newsrv->check_port = curproxy->defsrv.check_port;
4221 newsrv->inter = curproxy->defsrv.inter;
4222 newsrv->fastinter = curproxy->defsrv.fastinter;
4223 newsrv->downinter = curproxy->defsrv.downinter;
4224 newsrv->rise = curproxy->defsrv.rise;
4225 newsrv->fall = curproxy->defsrv.fall;
4226 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4227 newsrv->minconn = curproxy->defsrv.minconn;
4228 newsrv->maxconn = curproxy->defsrv.maxconn;
4229 newsrv->slowstart = curproxy->defsrv.slowstart;
4230 newsrv->onerror = curproxy->defsrv.onerror;
4231 newsrv->consecutive_errors_limit
4232 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004233#ifdef OPENSSL
4234 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4235#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004236 newsrv->uweight = newsrv->iweight
4237 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004238
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004239 newsrv->curfd = -1; /* no health-check in progress */
4240 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004242 cur_arg = 3;
4243 } else {
4244 newsrv = &curproxy->defsrv;
4245 cur_arg = 1;
4246 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004247
Willy Tarreaubaaee002006-06-26 02:48:02 +02004248 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004249 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004250 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004251
4252 if (!*args[cur_arg + 1]) {
4253 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4254 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004257 }
4258
4259 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004260 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004261
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004262 if (newsrv->puid <= 0) {
4263 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004264 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004267 }
4268
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004269 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4270 if (node) {
4271 struct server *target = container_of(node, struct server, conf.id);
4272 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4273 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
4276 }
4277 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004278 cur_arg += 2;
4279 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004280 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 newsrv->cookie = strdup(args[cur_arg + 1]);
4282 newsrv->cklen = strlen(args[cur_arg + 1]);
4283 cur_arg += 2;
4284 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004285 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004286 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4287 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4288 cur_arg += 2;
4289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004291 if (!*args[cur_arg + 1]) {
4292 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4293 file, linenum, args[cur_arg]);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004299 if (newsrv->rise <= 0) {
4300 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4301 file, linenum, args[cur_arg]);
4302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305
Willy Tarreau96839092010-03-29 10:02:24 +02004306 if (newsrv->health)
4307 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 cur_arg += 2;
4309 }
4310 else if (!strcmp(args[cur_arg], "fall")) {
4311 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004312
4313 if (!*args[cur_arg + 1]) {
4314 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4315 file, linenum, args[cur_arg]);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319
4320 if (newsrv->fall <= 0) {
4321 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4322 file, linenum, args[cur_arg]);
4323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
4326
Willy Tarreaubaaee002006-06-26 02:48:02 +02004327 cur_arg += 2;
4328 }
4329 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004330 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4331 if (err) {
4332 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4333 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004336 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004337 if (val <= 0) {
4338 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4339 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004342 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004343 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004344 cur_arg += 2;
4345 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004346 else if (!strcmp(args[cur_arg], "fastinter")) {
4347 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4348 if (err) {
4349 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4350 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004353 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004354 if (val <= 0) {
4355 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4356 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004359 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004360 newsrv->fastinter = val;
4361 cur_arg += 2;
4362 }
4363 else if (!strcmp(args[cur_arg], "downinter")) {
4364 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4365 if (err) {
4366 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4367 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004370 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004371 if (val <= 0) {
4372 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4373 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004376 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004377 newsrv->downinter = val;
4378 cur_arg += 2;
4379 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004380 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004381 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004382 if (!sk) {
4383 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004388 cur_arg += 2;
4389 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 else if (!strcmp(args[cur_arg], "port")) {
4391 newsrv->check_port = atol(args[cur_arg + 1]);
4392 cur_arg += 2;
4393 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004394 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395 newsrv->state |= SRV_BACKUP;
4396 cur_arg ++;
4397 }
Simon Hormanfa461682011-06-25 09:39:49 +09004398 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4399 newsrv->state |= SRV_NON_STICK;
4400 cur_arg ++;
4401 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004402 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4403 newsrv->state |= SRV_SEND_PROXY;
4404 cur_arg ++;
4405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 else if (!strcmp(args[cur_arg], "weight")) {
4407 int w;
4408 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004409 if (w < 0 || w > 256) {
4410 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004414 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004415 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 cur_arg += 2;
4417 }
4418 else if (!strcmp(args[cur_arg], "minconn")) {
4419 newsrv->minconn = atol(args[cur_arg + 1]);
4420 cur_arg += 2;
4421 }
4422 else if (!strcmp(args[cur_arg], "maxconn")) {
4423 newsrv->maxconn = atol(args[cur_arg + 1]);
4424 cur_arg += 2;
4425 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004426 else if (!strcmp(args[cur_arg], "maxqueue")) {
4427 newsrv->maxqueue = atol(args[cur_arg + 1]);
4428 cur_arg += 2;
4429 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004430 else if (!strcmp(args[cur_arg], "slowstart")) {
4431 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004432 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004433 if (err) {
4434 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4435 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004438 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004439 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004440 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4441 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004444 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004445 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004446 cur_arg += 2;
4447 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004448 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004449
4450 if (!*args[cur_arg + 1]) {
4451 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4452 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004455 }
4456
4457 newsrv->trackit = strdup(args[cur_arg + 1]);
4458
4459 cur_arg += 2;
4460 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004461 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 global.maxsock++;
4463 do_check = 1;
4464 cur_arg += 1;
4465 }
Willy Tarreau96839092010-03-29 10:02:24 +02004466 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4467 newsrv->state |= SRV_MAINTAIN;
4468 newsrv->state &= ~SRV_RUNNING;
4469 newsrv->health = 0;
4470 cur_arg += 1;
4471 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004472 else if (!strcmp(args[cur_arg], "ssl")) {
4473#ifdef USE_OPENSSL
4474 newsrv->use_ssl = 1;
4475 cur_arg += 1;
4476#else /* USE_OPENSSL */
4477 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4478 file, linenum, args[cur_arg]);
4479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481#endif /* USE_OPENSSL */
4482 }
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02004483 else if (!strcmp(args[cur_arg], "ciphers")) { /* use this SSL cipher suite */
4484#ifdef USE_OPENSSL
4485 if (!*args[cur_arg + 1]) {
4486 Alert("parsing [%s:%d] : '%s' : '%s' : missing cipher suite.\n",
4487 file, linenum, args[0], args[cur_arg]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
4491
4492 newsrv->ssl_ctx.ciphers = strdup(args[cur_arg + 1]);
4493
4494 cur_arg += 2;
4495 continue;
4496#else
4497 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4498 file, linenum, args[0], args[cur_arg]);
4499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
4501#endif
4502 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02004503 else if (!strcmp(args[cur_arg], "nosslv3")) {
4504#ifdef USE_OPENSSL
4505 newsrv->ssl_ctx.nosslv3 = 1;
4506 cur_arg += 1;
4507#else /* USE_OPENSSL */
4508 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4509 file, linenum, args[cur_arg]);
4510 err_code |= ERR_ALERT | ERR_FATAL;
4511 goto out;
4512#endif /* USE_OPENSSL */
4513 }
4514 else if (!strcmp(args[cur_arg], "notlsv1")) {
4515#ifdef USE_OPENSSL
4516 newsrv->ssl_ctx.notlsv1 = 1;
4517 cur_arg += 1;
4518#else /* USE_OPENSSL */
4519 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4520 file, linenum, args[cur_arg]);
4521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523#endif /* USE_OPENSSL */
4524 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004525 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004526 if (!strcmp(args[cur_arg + 1], "none"))
4527 newsrv->observe = HANA_OBS_NONE;
4528 else if (!strcmp(args[cur_arg + 1], "layer4"))
4529 newsrv->observe = HANA_OBS_LAYER4;
4530 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4531 if (curproxy->mode != PR_MODE_HTTP) {
4532 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4533 file, linenum, args[cur_arg + 1]);
4534 err_code |= ERR_ALERT;
4535 }
4536 newsrv->observe = HANA_OBS_LAYER7;
4537 }
4538 else {
4539 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004540 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004541 file, linenum, args[cur_arg], args[cur_arg + 1]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545
4546 cur_arg += 2;
4547 }
4548 else if (!strcmp(args[cur_arg], "on-error")) {
4549 if (!strcmp(args[cur_arg + 1], "fastinter"))
4550 newsrv->onerror = HANA_ONERR_FASTINTER;
4551 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4552 newsrv->onerror = HANA_ONERR_FAILCHK;
4553 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4554 newsrv->onerror = HANA_ONERR_SUDDTH;
4555 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4556 newsrv->onerror = HANA_ONERR_MARKDWN;
4557 else {
4558 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004559 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004560 file, linenum, args[cur_arg], args[cur_arg + 1]);
4561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
4563 }
4564
4565 cur_arg += 2;
4566 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004567 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4568 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4569 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4570 else {
4571 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4572 file, linenum, args[cur_arg], args[cur_arg + 1]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576
4577 cur_arg += 2;
4578 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004579 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4580 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4581 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4582 else {
4583 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4584 file, linenum, args[cur_arg], args[cur_arg + 1]);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588
4589 cur_arg += 2;
4590 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004591 else if (!strcmp(args[cur_arg], "error-limit")) {
4592 if (!*args[cur_arg + 1]) {
4593 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4594 file, linenum, args[cur_arg]);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
4598
4599 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4600
4601 if (newsrv->consecutive_errors_limit <= 0) {
4602 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4603 file, linenum, args[cur_arg]);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004607 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004608 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004609 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004610 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004611 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004612
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004614#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004615 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004616 file, linenum, "source", "usesrc");
4617#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004618 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004620#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 }
4624 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004625 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4626 if (!sk) {
4627 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
4630 }
4631 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004632
4633 if (port_low != port_high) {
4634 int i;
4635 if (port_low <= 0 || port_low > 65535 ||
4636 port_high <= 0 || port_high > 65535 ||
4637 port_low > port_high) {
4638 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4639 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004642 }
4643 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4644 for (i = 0; i < newsrv->sport_range->size; i++)
4645 newsrv->sport_range->ports[i] = port_low + i;
4646 }
4647
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004649 while (*(args[cur_arg])) {
4650 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004651#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4652#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004653 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4654 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4655 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004656 err_code |= ERR_ALERT | ERR_FATAL;
4657 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004658 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004659#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004660 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004661 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004662 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004665 }
4666 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004667 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004668 newsrv->state |= SRV_TPROXY_CLI;
4669 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004670 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004671 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004672 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4673 char *name, *end;
4674
4675 name = args[cur_arg+1] + 7;
4676 while (isspace(*name))
4677 name++;
4678
4679 end = name;
4680 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4681 end++;
4682
4683 newsrv->state &= ~SRV_TPROXY_MASK;
4684 newsrv->state |= SRV_TPROXY_DYN;
4685 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4686 newsrv->bind_hdr_len = end - name;
4687 memcpy(newsrv->bind_hdr_name, name, end - name);
4688 newsrv->bind_hdr_name[end-name] = '\0';
4689 newsrv->bind_hdr_occ = -1;
4690
4691 /* now look for an occurrence number */
4692 while (isspace(*end))
4693 end++;
4694 if (*end == ',') {
4695 end++;
4696 name = end;
4697 if (*end == '-')
4698 end++;
4699 while (isdigit(*end))
4700 end++;
4701 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4702 }
4703
4704 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4705 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4706 " occurrences values smaller than %d.\n",
4707 file, linenum, MAX_HDR_HISTORY);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004711 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004712 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004713 if (!sk) {
4714 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
4718 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004719 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004720 }
4721 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004722#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004723 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004724#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004725 cur_arg += 2;
4726 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004728 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004729 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004732#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4733 } /* "usesrc" */
4734
4735 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4736#ifdef SO_BINDTODEVICE
4737 if (!*args[cur_arg + 1]) {
4738 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004742 }
4743 if (newsrv->iface_name)
4744 free(newsrv->iface_name);
4745
4746 newsrv->iface_name = strdup(args[cur_arg + 1]);
4747 newsrv->iface_len = strlen(newsrv->iface_name);
4748 global.last_checks |= LSTCHK_NETADM;
4749#else
4750 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4751 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004754#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004755 cur_arg += 2;
4756 continue;
4757 }
4758 /* this keyword in not an option of "source" */
4759 break;
4760 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004762 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004763 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4764 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004765 err_code |= ERR_ALERT | ERR_FATAL;
4766 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004769 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004770 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 +01004771 file, linenum, newsrv->id);
4772 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004773 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 +01004774 file, linenum);
4775
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
4779 }
4780
4781 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004782 if (newsrv->trackit) {
4783 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4784 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004787 }
4788
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004789 /* try to get the port from check_addr if check_port not set */
4790 if (!newsrv->check_port)
4791 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004792
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4794 newsrv->check_port = realport; /* by default */
4795 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004796 /* not yet valid, because no port was set on
4797 * the server either. We'll check if we have
4798 * a known port on the first listener.
4799 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004800 struct listener *l = curproxy->listen;
4801 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4802 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004803 }
4804 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004805 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4806 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004810
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004811 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004812 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004813 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4814 err_code |= ERR_ALERT | ERR_ABORT;
4815 goto out;
4816 }
4817
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004818 /* Allocate buffer for partial check results... */
4819 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4820 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4821 err_code |= ERR_ALERT | ERR_ABORT;
4822 goto out;
4823 }
4824
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004825 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 newsrv->state |= SRV_CHECKED;
4827 }
4828
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004829 if (!defsrv) {
4830 if (newsrv->state & SRV_BACKUP)
4831 curproxy->srv_bck++;
4832 else
4833 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004834
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004835 newsrv->prev_state = newsrv->state;
4836 }
William Lallemanda73203e2012-03-12 12:48:57 +01004837 }
4838
4839 else if (strcmp(args[0], "unique-id-format") == 0) {
4840 if (!*(args[1])) {
4841 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004845 free(curproxy->uniqueid_format_string);
4846 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004847 }
William Lallemanda73203e2012-03-12 12:48:57 +01004848
4849 else if (strcmp(args[0], "unique-id-header") == 0) {
4850 if (!*(args[1])) {
4851 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
4855 free(curproxy->header_unique_id);
4856 curproxy->header_unique_id = strdup(args[1]);
4857 }
4858
William Lallemand723b73a2012-02-08 16:37:49 +01004859 else if (strcmp(args[0], "log-format") == 0) {
4860 if (!*(args[1])) {
4861 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
4864 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004865
4866 if (curproxy->logformat_string != default_http_log_format &&
4867 curproxy->logformat_string != default_tcp_log_format &&
4868 curproxy->logformat_string != clf_http_log_format)
4869 free(curproxy->logformat_string);
4870 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
William Lallemand723b73a2012-02-08 16:37:49 +01004872
William Lallemand0f99e342011-10-12 17:50:54 +02004873 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4874 /* delete previous herited or defined syslog servers */
4875 struct logsrv *back;
4876
4877 if (*(args[1]) != 0) {
4878 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881 }
4882
William Lallemand723b73a2012-02-08 16:37:49 +01004883 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4884 LIST_DEL(&tmplogsrv->list);
4885 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004886 }
4887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004889 struct logsrv *logsrv;
4890
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004892 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004893 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004894 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004895 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004896 LIST_INIT(&node->list);
4897 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004901
4902 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903
William Lallemand0f99e342011-10-12 17:50:54 +02004904 logsrv->facility = get_log_facility(args[2]);
4905 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
4911
William Lallemand0f99e342011-10-12 17:50:54 +02004912 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004914 logsrv->level = get_log_level(args[3]);
4915 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 }
4922
William Lallemand0f99e342011-10-12 17:50:54 +02004923 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004924 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004925 logsrv->minlvl = get_log_level(args[4]);
4926 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004927 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
4930
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004931 }
4932 }
4933
Robert Tsai81ae1952007-12-05 10:47:29 +01004934 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004935 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004936 if (!sk) {
4937 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004938 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
4941 }
William Lallemand0f99e342011-10-12 17:50:54 +02004942 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004943 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004944 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004945 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004946 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
4949 }
William Lallemand0f99e342011-10-12 17:50:54 +02004950 logsrv->addr = *sk;
4951 if (!get_host_port(&logsrv->addr))
4952 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
William Lallemand0f99e342011-10-12 17:50:54 +02004954
4955 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
4957 else {
4958 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4959 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963 }
4964 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004965 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004966 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004967
Willy Tarreau977b8e42006-12-29 14:19:17 +01004968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004970
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004972 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4973 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004977
4978 /* we must first clear any optional default setting */
4979 curproxy->options &= ~PR_O_TPXY_MASK;
4980 free(curproxy->iface_name);
4981 curproxy->iface_name = NULL;
4982 curproxy->iface_len = 0;
4983
Willy Tarreaud5191e72010-02-09 20:50:45 +01004984 sk = str2sa(args[1]);
4985 if (!sk) {
4986 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989 }
4990 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004992
4993 cur_arg = 2;
4994 while (*(args[cur_arg])) {
4995 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004996#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4997#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004998 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4999 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5000 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005003 }
5004#endif
5005 if (!*args[cur_arg + 1]) {
5006 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5007 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005010 }
5011
5012 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005013 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005014 curproxy->options |= PR_O_TPXY_CLI;
5015 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005016 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005018 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5019 char *name, *end;
5020
5021 name = args[cur_arg+1] + 7;
5022 while (isspace(*name))
5023 name++;
5024
5025 end = name;
5026 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5027 end++;
5028
5029 curproxy->options &= ~PR_O_TPXY_MASK;
5030 curproxy->options |= PR_O_TPXY_DYN;
5031 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5032 curproxy->bind_hdr_len = end - name;
5033 memcpy(curproxy->bind_hdr_name, name, end - name);
5034 curproxy->bind_hdr_name[end-name] = '\0';
5035 curproxy->bind_hdr_occ = -1;
5036
5037 /* now look for an occurrence number */
5038 while (isspace(*end))
5039 end++;
5040 if (*end == ',') {
5041 end++;
5042 name = end;
5043 if (*end == '-')
5044 end++;
5045 while (isdigit(*end))
5046 end++;
5047 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5048 }
5049
5050 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5051 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5052 " occurrences values smaller than %d.\n",
5053 file, linenum, MAX_HDR_HISTORY);
5054 err_code |= ERR_ALERT | ERR_FATAL;
5055 goto out;
5056 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005057 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005058 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005059 if (!sk) {
5060 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
5063 }
5064 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005065 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 }
5067 global.last_checks |= LSTCHK_NETADM;
5068#if !defined(CONFIG_HAP_LINUX_TPROXY)
5069 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005070#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005071#else /* no TPROXY support */
5072 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005073 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005076#endif
5077 cur_arg += 2;
5078 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005079 }
5080
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005081 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5082#ifdef SO_BINDTODEVICE
5083 if (!*args[cur_arg + 1]) {
5084 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5085 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005088 }
5089 if (curproxy->iface_name)
5090 free(curproxy->iface_name);
5091
5092 curproxy->iface_name = strdup(args[cur_arg + 1]);
5093 curproxy->iface_len = strlen(curproxy->iface_name);
5094 global.last_checks |= LSTCHK_NETADM;
5095#else
5096 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5097 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005100#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005101 cur_arg += 2;
5102 continue;
5103 }
5104 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
5105 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005110 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5111 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5112 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005116 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005117 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5119 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123
5124 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005125 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005126 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005131 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005132 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005133 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136 }
5137 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005138 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005139 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005140 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 }
5144 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005145 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005146 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005147 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
5151 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005153 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005154 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005155 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005158 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005160 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005161 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005162 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005163 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005164 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005165 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005167 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005168 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005169 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005170 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005171 }
5172 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005174 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005175 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005177 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005178 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5182 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005185 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005186
5187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005188 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005189 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192 }
5193 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005195 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005196 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005197 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199 }
5200 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 }
5207 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005209 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 }
5214 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005215 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005216 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005217 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005221 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005222 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005223 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005224 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005226 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005229 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005230
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 if (curproxy == &defproxy) {
5232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005236 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005237 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 if (*(args[1]) == 0) {
5240 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005244
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005245 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005246 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5247 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5248 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
5251 }
5252 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5253 }
5254 else if (*args[2]) {
5255 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5256 file, linenum, args[0], args[2]);
5257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
5259 }
5260
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005261 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005262 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005263 wl->s = strdup(args[1]);
5264 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005265 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5270 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005274
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005276 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005277 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
5281 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005283 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005284 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005285 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005287 }
5288 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005289 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005290 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005291 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005292 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294 }
5295 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005296 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 }
5302
Willy Tarreauade5ec42010-01-28 19:33:49 +01005303 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005304 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005305 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005306 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 }
5309 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005310 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005311 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005312 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005313 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
5316 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005317 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005318 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005319 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005320 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 }
5323 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005324 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 if (curproxy == &defproxy) {
5327 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_ALERT | ERR_FATAL;
5329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005331 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005332 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 if (*(args[1]) == 0) {
5335 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 }
5339
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005340 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005341 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5342 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5343 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005344 err_code |= ERR_ALERT | ERR_FATAL;
5345 goto out;
5346 }
5347 err_code |= warnif_cond_requires_req(cond, file, linenum);
5348 }
5349 else if (*args[2]) {
5350 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5351 file, linenum, args[0], args[2]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005356 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005357 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005358 wl->s = strdup(args[1]);
5359 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361 else if (!strcmp(args[0], "errorloc") ||
5362 !strcmp(args[0], "errorloc302") ||
5363 !strcmp(args[0], "errorloc303")) { /* error location */
5364 int errnum, errlen;
5365 char *err;
5366
Willy Tarreau977b8e42006-12-29 14:19:17 +01005367 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005368 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005369
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005371 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005372 err_code |= ERR_ALERT | ERR_FATAL;
5373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
5375
5376 errnum = atol(args[1]);
5377 if (!strcmp(args[0], "errorloc303")) {
5378 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5379 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5380 } else {
5381 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5382 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5383 }
5384
Willy Tarreau0f772532006-12-23 20:51:41 +01005385 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5386 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005387 chunk_destroy(&curproxy->errmsg[rc]);
5388 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005389 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005392
5393 if (rc >= HTTP_ERR_SIZE) {
5394 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5395 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 free(err);
5397 }
5398 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005399 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5400 int errnum, errlen, fd;
5401 char *err;
5402 struct stat stat;
5403
5404 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005405 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005406
5407 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005408 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005411 }
5412
5413 fd = open(args[2], O_RDONLY);
5414 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5415 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5416 file, linenum, args[2], args[1]);
5417 if (fd >= 0)
5418 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005421 }
5422
Willy Tarreau27a674e2009-08-17 07:23:33 +02005423 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005424 errlen = stat.st_size;
5425 } else {
5426 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005427 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005428 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005429 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005430 }
5431
5432 err = malloc(errlen); /* malloc() must succeed during parsing */
5433 errnum = read(fd, err, errlen);
5434 if (errnum != errlen) {
5435 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5436 file, linenum, args[2], args[1]);
5437 close(fd);
5438 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005441 }
5442 close(fd);
5443
5444 errnum = atol(args[1]);
5445 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5446 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005447 chunk_destroy(&curproxy->errmsg[rc]);
5448 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005449 break;
5450 }
5451 }
5452
5453 if (rc >= HTTP_ERR_SIZE) {
5454 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5455 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005457 free(err);
5458 }
5459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005461 struct cfg_kw_list *kwl;
5462 int index;
5463
5464 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5465 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5466 if (kwl->kw[index].section != CFG_LISTEN)
5467 continue;
5468 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5469 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005470 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005471 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005472 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005473 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005474 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005475 err_code |= ERR_ALERT | ERR_FATAL;
5476 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005477 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005478 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005479 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005480 err_code |= ERR_WARN;
5481 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005482 }
Willy Tarreau93893792009-07-23 13:19:11 +02005483 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005484 }
5485 }
5486 }
5487
Willy Tarreau6daf3432008-01-22 16:44:08 +01005488 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005489 err_code |= ERR_ALERT | ERR_FATAL;
5490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 }
Willy Tarreau93893792009-07-23 13:19:11 +02005492 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005493 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005494 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495}
5496
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005497int
5498cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5499{
5500
5501 int err_code = 0;
5502 const char *err;
5503
5504 if (!strcmp(args[0], "userlist")) { /* new userlist */
5505 struct userlist *newul;
5506
5507 if (!*args[1]) {
5508 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5509 file, linenum, args[0]);
5510 err_code |= ERR_ALERT | ERR_FATAL;
5511 goto out;
5512 }
5513
5514 err = invalid_char(args[1]);
5515 if (err) {
5516 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5517 file, linenum, *err, args[0], args[1]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521
5522 for (newul = userlist; newul; newul = newul->next)
5523 if (!strcmp(newul->name, args[1])) {
5524 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5525 file, linenum, args[1]);
5526 err_code |= ERR_WARN;
5527 goto out;
5528 }
5529
5530 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5531 if (!newul) {
5532 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5533 err_code |= ERR_ALERT | ERR_ABORT;
5534 goto out;
5535 }
5536
5537 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5538 newul->name = strdup(args[1]);
5539
5540 if (!newul->groupusers | !newul->name) {
5541 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5542 err_code |= ERR_ALERT | ERR_ABORT;
5543 goto out;
5544 }
5545
5546 newul->next = userlist;
5547 userlist = newul;
5548
5549 } else if (!strcmp(args[0], "group")) { /* new group */
5550 int cur_arg, i;
5551 const char *err;
5552
5553 if (!*args[1]) {
5554 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5555 file, linenum, args[0]);
5556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
5558 }
5559
5560 err = invalid_char(args[1]);
5561 if (err) {
5562 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5563 file, linenum, *err, args[0], args[1]);
5564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
5566 }
5567
5568 for(i = 0; i < userlist->grpcnt; i++)
5569 if (!strcmp(userlist->groups[i], args[1])) {
5570 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5571 file, linenum, args[1], userlist->name);
5572 err_code |= ERR_ALERT;
5573 goto out;
5574 }
5575
5576 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5577 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5578 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
5581 }
5582
5583 cur_arg = 2;
5584
5585 while (*args[cur_arg]) {
5586 if (!strcmp(args[cur_arg], "users")) {
5587 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5588 cur_arg += 2;
5589 continue;
5590 } else {
5591 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5592 file, linenum, args[0]);
5593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
5595 }
5596 }
5597
5598 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5599 } else if (!strcmp(args[0], "user")) { /* new user */
5600 struct auth_users *newuser;
5601 int cur_arg;
5602
5603 if (!*args[1]) {
5604 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5605 file, linenum, args[0]);
5606 err_code |= ERR_ALERT | ERR_FATAL;
5607 goto out;
5608 }
5609
5610 for (newuser = userlist->users; newuser; newuser = newuser->next)
5611 if (!strcmp(newuser->user, args[1])) {
5612 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5613 file, linenum, args[1], userlist->name);
5614 err_code |= ERR_ALERT;
5615 goto out;
5616 }
5617
5618 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5619 if (!newuser) {
5620 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5621 err_code |= ERR_ALERT | ERR_ABORT;
5622 goto out;
5623 }
5624
5625 newuser->user = strdup(args[1]);
5626
5627 newuser->next = userlist->users;
5628 userlist->users = newuser;
5629
5630 cur_arg = 2;
5631
5632 while (*args[cur_arg]) {
5633 if (!strcmp(args[cur_arg], "password")) {
5634#ifndef CONFIG_HAP_CRYPT
5635 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5636 file, linenum);
5637 err_code |= ERR_ALERT;
5638#endif
5639 newuser->pass = strdup(args[cur_arg + 1]);
5640 cur_arg += 2;
5641 continue;
5642 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5643 newuser->pass = strdup(args[cur_arg + 1]);
5644 newuser->flags |= AU_O_INSECURE;
5645 cur_arg += 2;
5646 continue;
5647 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005648 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005649 cur_arg += 2;
5650 continue;
5651 } else {
5652 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5653 file, linenum, args[0]);
5654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657 }
5658 } else {
5659 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 }
5662
5663out:
5664 return err_code;
5665}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666
5667/*
5668 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005669 * Returns the error code, 0 if OK, or any combination of :
5670 * - ERR_ABORT: must abort ASAP
5671 * - ERR_FATAL: we can continue parsing but not start the service
5672 * - ERR_WARN: a warning has been emitted
5673 * - ERR_ALERT: an alert has been emitted
5674 * Only the two first ones can stop processing, the two others are just
5675 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005677int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005678{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005679 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 FILE *f;
5681 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005683 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 if ((f=fopen(file,"r")) == NULL)
5686 return -1;
5687
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005688 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005689 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005690 char *end;
5691 char *args[MAX_LINE_ARGS + 1];
5692 char *line = thisline;
5693
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 linenum++;
5695
5696 end = line + strlen(line);
5697
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005698 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5699 /* Check if we reached the limit and the last char is not \n.
5700 * Watch out for the last line without the terminating '\n'!
5701 */
5702 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005703 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005704 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005705 }
5706
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005708 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005709 line++;
5710
5711 arg = 0;
5712 args[arg] = line;
5713
5714 while (*line && arg < MAX_LINE_ARGS) {
5715 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5716 * C equivalent value. Other combinations left unchanged (eg: \1).
5717 */
5718 if (*line == '\\') {
5719 int skip = 0;
5720 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5721 *line = line[1];
5722 skip = 1;
5723 }
5724 else if (line[1] == 'r') {
5725 *line = '\r';
5726 skip = 1;
5727 }
5728 else if (line[1] == 'n') {
5729 *line = '\n';
5730 skip = 1;
5731 }
5732 else if (line[1] == 't') {
5733 *line = '\t';
5734 skip = 1;
5735 }
5736 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005737 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 unsigned char hex1, hex2;
5739 hex1 = toupper(line[2]) - '0';
5740 hex2 = toupper(line[3]) - '0';
5741 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5742 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5743 *line = (hex1<<4) + hex2;
5744 skip = 3;
5745 }
5746 else {
5747 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
5750 }
5751 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005752 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 end -= skip;
5754 }
5755 line++;
5756 }
5757 else if (*line == '#' || *line == '\n' || *line == '\r') {
5758 /* end of string, end of loop */
5759 *line = 0;
5760 break;
5761 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005762 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005764 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005765 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 line++;
5767 args[++arg] = line;
5768 }
5769 else {
5770 line++;
5771 }
5772 }
5773
5774 /* empty line */
5775 if (!**args)
5776 continue;
5777
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005778 if (*line) {
5779 /* we had to stop due to too many args.
5780 * Let's terminate the string, print the offending part then cut the
5781 * last arg.
5782 */
5783 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5784 line++;
5785 *line = '\0';
5786
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005787 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005788 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005789 err_code |= ERR_ALERT | ERR_FATAL;
5790 args[arg] = line;
5791 }
5792
Willy Tarreau540abe42007-05-02 20:50:16 +02005793 /* zero out remaining args and ensure that at least one entry
5794 * is zeroed out.
5795 */
5796 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 args[arg] = line;
5798 }
5799
Willy Tarreau3842f002009-06-14 11:39:52 +02005800 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005801 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005802 char *tmp;
5803
Willy Tarreau3842f002009-06-14 11:39:52 +02005804 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005805 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005806 for (arg=0; *args[arg+1]; arg++)
5807 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005808 *tmp = '\0'; // fix the next arg to \0
5809 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005810 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005811 else if (!strcmp(args[0], "default")) {
5812 kwm = KWM_DEF;
5813 for (arg=0; *args[arg+1]; arg++)
5814 args[arg] = args[arg+1]; // shift args after inversion
5815 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005816
William Lallemand0f99e342011-10-12 17:50:54 +02005817 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5818 strcmp(args[0], "log") != 0) {
5819 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005820 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005821 }
5822
Willy Tarreau977b8e42006-12-29 14:19:17 +01005823 if (!strcmp(args[0], "listen") ||
5824 !strcmp(args[0], "frontend") ||
5825 !strcmp(args[0], "backend") ||
5826 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005827 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005829 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005830 cursection = strdup(args[0]);
5831 }
5832 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005834 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005835 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005836 }
5837 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005838 confsect = CFG_USERLIST;
5839 free(cursection);
5840 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005841 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005842 else if (!strcmp(args[0], "peers")) {
5843 confsect = CFG_PEERS;
5844 free(cursection);
5845 cursection = strdup(args[0]);
5846 }
5847
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 /* else it's a section keyword */
5849
5850 switch (confsect) {
5851 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005852 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005853 break;
5854 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005855 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005857 case CFG_USERLIST:
5858 err_code |= cfg_parse_users(file, linenum, args, kwm);
5859 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005860 case CFG_PEERS:
5861 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5862 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005863 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005864 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005865 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005867
5868 if (err_code & ERR_ABORT)
5869 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005871 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005872 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005874 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005875}
5876
Willy Tarreaubb925012009-07-23 13:36:36 +02005877/*
5878 * Returns the error code, 0 if OK, or any combination of :
5879 * - ERR_ABORT: must abort ASAP
5880 * - ERR_FATAL: we can continue parsing but not start the service
5881 * - ERR_WARN: a warning has been emitted
5882 * - ERR_ALERT: an alert has been emitted
5883 * Only the two first ones can stop processing, the two others are just
5884 * indicators.
5885 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005886int check_config_validity()
5887{
5888 int cfgerr = 0;
5889 struct proxy *curproxy = NULL;
5890 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005891 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005892 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005893 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894
5895 /*
5896 * Now, check for the integrity of all that we have collected.
5897 */
5898
5899 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005900 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005902 /* first, we will invert the proxy list order */
5903 curproxy = NULL;
5904 while (proxy) {
5905 struct proxy *next;
5906
5907 next = proxy->next;
5908 proxy->next = curproxy;
5909 curproxy = proxy;
5910 if (!next)
5911 break;
5912 proxy = next;
5913 }
5914
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005916 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005917 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005918 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005919 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005920 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005921 unsigned int next_id;
5922
5923 if (!curproxy->uuid) {
5924 /* proxy ID not set, use automatic numbering with first
5925 * spare entry starting with next_pxid.
5926 */
5927 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5928 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5929 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005930 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005931 next_pxid++;
5932
Willy Tarreau55ea7572007-06-17 19:56:27 +02005933
Willy Tarreaubaaee002006-06-26 02:48:02 +02005934 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005935 /* ensure we don't keep listeners uselessly bound */
5936 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 curproxy = curproxy->next;
5938 continue;
5939 }
5940
Willy Tarreauff01a212009-03-15 13:46:16 +01005941 switch (curproxy->mode) {
5942 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005943 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005944 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005945 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5946 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005947 cfgerr++;
5948 }
5949
5950 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005951 Warning("config : servers will be ignored for %s '%s'.\n",
5952 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005953 break;
5954
5955 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005956 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005957 break;
5958
5959 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005960 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005961 break;
5962 }
5963
5964 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005965 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5966 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 cfgerr++;
5968 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005969
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005970 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005971 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005972 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005973 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5974 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005975 cfgerr++;
5976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005978 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5980 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005981 cfgerr++;
5982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005984 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005985 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5986 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005987 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005988 }
5989 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005990 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005991 /* If no LB algo is set in a backend, and we're not in
5992 * transparent mode, dispatch mode nor proxy mode, we
5993 * want to use balance roundrobin by default.
5994 */
5995 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5996 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 }
5998 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005999
Willy Tarreau1620ec32011-08-06 17:05:02 +02006000 if (curproxy->options & PR_O_DISPATCH)
6001 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6002 else if (curproxy->options & PR_O_HTTP_PROXY)
6003 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6004 else if (curproxy->options & PR_O_TRANSP)
6005 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006006
Willy Tarreau1620ec32011-08-06 17:05:02 +02006007 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6008 if (curproxy->options & PR_O_DISABLE404) {
6009 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6010 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6011 err_code |= ERR_WARN;
6012 curproxy->options &= ~PR_O_DISABLE404;
6013 }
6014 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6015 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6016 "send-state", proxy_type_str(curproxy), curproxy->id);
6017 err_code |= ERR_WARN;
6018 curproxy->options &= ~PR_O2_CHK_SNDST;
6019 }
Willy Tarreauef781042010-01-27 11:53:01 +01006020 }
6021
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006022 /* if a default backend was specified, let's find it */
6023 if (curproxy->defbe.name) {
6024 struct proxy *target;
6025
Alex Williams96532db2009-11-01 21:27:13 -05006026 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006027 if (!target) {
6028 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6029 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006030 cfgerr++;
6031 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006032 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6033 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006034 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006035 } else {
6036 free(curproxy->defbe.name);
6037 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006038 /* we force the backend to be present on at least all of
6039 * the frontend's processes.
6040 */
6041 target->bind_proc = curproxy->bind_proc ?
6042 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006043
6044 /* Emit a warning if this proxy also has some servers */
6045 if (curproxy->srv) {
6046 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6047 curproxy->id);
6048 err_code |= ERR_WARN;
6049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006050 }
6051 }
6052
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006053 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006054 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6055 /* map jump target for ACT_SETBE in req_rep chain */
6056 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006057 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006058 struct proxy *target;
6059
Willy Tarreaua496b602006-12-17 23:15:24 +01006060 if (exp->action != ACT_SETBE)
6061 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006062
Alex Williams96532db2009-11-01 21:27:13 -05006063 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006064 if (!target) {
6065 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6066 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006067 cfgerr++;
6068 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006069 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6070 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006071 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006072 } else {
6073 free((void *)exp->replace);
6074 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006075 /* we force the backend to be present on at least all of
6076 * the frontend's processes.
6077 */
6078 target->bind_proc = curproxy->bind_proc ?
6079 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006080 }
6081 }
6082 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006083
6084 /* find the target proxy for 'use_backend' rules */
6085 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006086 struct proxy *target;
6087
Alex Williams96532db2009-11-01 21:27:13 -05006088 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006089
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006090 if (!target) {
6091 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6092 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006093 cfgerr++;
6094 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006095 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6096 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006097 cfgerr++;
6098 } else {
6099 free((void *)rule->be.name);
6100 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006101 /* we force the backend to be present on at least all of
6102 * the frontend's processes.
6103 */
6104 target->bind_proc = curproxy->bind_proc ?
6105 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006106 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006107 }
6108
6109 /* find the target proxy for 'use_backend' rules */
6110 list_for_each_entry(srule, &curproxy->server_rules, list) {
6111 struct server *target = findserver(curproxy, srule->srv.name);
6112
6113 if (!target) {
6114 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6115 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6116 cfgerr++;
6117 continue;
6118 }
6119 free((void *)srule->srv.name);
6120 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006121 }
6122
Emeric Brunb982a3d2010-01-04 15:45:53 +01006123 /* find the target table for 'stick' rules */
6124 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6125 struct proxy *target;
6126
Emeric Brun1d33b292010-01-04 15:47:17 +01006127 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6128 if (mrule->flags & STK_IS_STORE)
6129 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6130
Emeric Brunb982a3d2010-01-04 15:45:53 +01006131 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006132 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006133 else
6134 target = curproxy;
6135
6136 if (!target) {
6137 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6138 curproxy->id, mrule->table.name);
6139 cfgerr++;
6140 }
6141 else if (target->table.size == 0) {
6142 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6143 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6144 cfgerr++;
6145 }
Willy Tarreau12785782012-04-27 21:37:17 +02006146 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6147 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006148 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6149 cfgerr++;
6150 }
6151 else {
6152 free((void *)mrule->table.name);
6153 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006154 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006155 }
6156 }
6157
6158 /* find the target table for 'store response' rules */
6159 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6160 struct proxy *target;
6161
Emeric Brun1d33b292010-01-04 15:47:17 +01006162 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6163
Emeric Brunb982a3d2010-01-04 15:45:53 +01006164 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006165 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006166 else
6167 target = curproxy;
6168
6169 if (!target) {
6170 Alert("Proxy '%s': unable to find store table '%s'.\n",
6171 curproxy->id, mrule->table.name);
6172 cfgerr++;
6173 }
6174 else if (target->table.size == 0) {
6175 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6176 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6177 cfgerr++;
6178 }
Willy Tarreau12785782012-04-27 21:37:17 +02006179 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6180 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006181 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6182 cfgerr++;
6183 }
6184 else {
6185 free((void *)mrule->table.name);
6186 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006187 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006188 }
6189 }
6190
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006191 /* find the target table for 'tcp-request' layer 4 rules */
6192 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6193 struct proxy *target;
6194
Willy Tarreau56123282010-08-06 19:06:56 +02006195 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006196 continue;
6197
6198 if (trule->act_prm.trk_ctr.table.n)
6199 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6200 else
6201 target = curproxy;
6202
6203 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006204 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6205 curproxy->id, trule->act_prm.trk_ctr.table.n,
6206 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006207 cfgerr++;
6208 }
6209 else if (target->table.size == 0) {
6210 Alert("Proxy '%s': table '%s' used but not configured.\n",
6211 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6212 cfgerr++;
6213 }
6214 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006215 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 +02006216 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6217 cfgerr++;
6218 }
6219 else {
6220 free(trule->act_prm.trk_ctr.table.n);
6221 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006222 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006223 * to pass a list of counters to track and allocate them right here using
6224 * stktable_alloc_data_type().
6225 */
6226 }
6227 }
6228
Willy Tarreaud1f96522010-08-03 19:34:32 +02006229 /* find the target table for 'tcp-request' layer 6 rules */
6230 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6231 struct proxy *target;
6232
Willy Tarreau56123282010-08-06 19:06:56 +02006233 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006234 continue;
6235
6236 if (trule->act_prm.trk_ctr.table.n)
6237 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6238 else
6239 target = curproxy;
6240
6241 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006242 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6243 curproxy->id, trule->act_prm.trk_ctr.table.n,
6244 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006245 cfgerr++;
6246 }
6247 else if (target->table.size == 0) {
6248 Alert("Proxy '%s': table '%s' used but not configured.\n",
6249 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6250 cfgerr++;
6251 }
6252 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006253 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 +02006254 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6255 cfgerr++;
6256 }
6257 else {
6258 free(trule->act_prm.trk_ctr.table.n);
6259 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006260 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006261 * to pass a list of counters to track and allocate them right here using
6262 * stktable_alloc_data_type().
6263 */
6264 }
6265 }
6266
Emeric Brun32da3c42010-09-23 18:39:19 +02006267 if (curproxy->table.peers.name) {
6268 struct peers *curpeers = peers;
6269
6270 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6271 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6272 free((void *)curproxy->table.peers.name);
6273 curproxy->table.peers.p = peers;
6274 break;
6275 }
6276 }
6277
6278 if (!curpeers) {
6279 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6280 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006281 free((void *)curproxy->table.peers.name);
6282 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006283 cfgerr++;
6284 }
6285 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006286 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6287 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006288 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006289 cfgerr++;
6290 }
6291 }
6292
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006293 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006294 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006295 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6296 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6297 "proxy", curproxy->id);
6298 cfgerr++;
6299 goto out_uri_auth_compat;
6300 }
6301
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006302 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006303 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006304 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006305 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006306
Willy Tarreau95fa4692010-02-01 13:05:50 +01006307 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6308 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006309
6310 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006311 uri_auth_compat_req[i++] = "realm";
6312 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6313 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006314
Willy Tarreau95fa4692010-02-01 13:05:50 +01006315 uri_auth_compat_req[i++] = "unless";
6316 uri_auth_compat_req[i++] = "{";
6317 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6318 uri_auth_compat_req[i++] = "}";
6319 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006320
Willy Tarreauff011f22011-01-06 17:51:27 +01006321 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6322 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006323 cfgerr++;
6324 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006325 }
6326
Willy Tarreauff011f22011-01-06 17:51:27 +01006327 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006328
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006329 if (curproxy->uri_auth->auth_realm) {
6330 free(curproxy->uri_auth->auth_realm);
6331 curproxy->uri_auth->auth_realm = NULL;
6332 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006333
6334 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006335 }
6336out_uri_auth_compat:
6337
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006338 cfgerr += acl_find_targets(curproxy);
6339
Willy Tarreau2738a142006-07-08 17:28:09 +02006340 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006341 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006342 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006343 (!curproxy->timeout.connect ||
6344 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006345 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006346 " | While not properly invalid, you will certainly encounter various problems\n"
6347 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006348 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006349 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006350 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006351 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006352
Willy Tarreau1fa31262007-12-03 00:36:16 +01006353 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6354 * We must still support older configurations, so let's find out whether those
6355 * parameters have been set or must be copied from contimeouts.
6356 */
6357 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006358 if (!curproxy->timeout.tarpit ||
6359 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006360 /* tarpit timeout not set. We search in the following order:
6361 * default.tarpit, curr.connect, default.connect.
6362 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006363 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006364 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006365 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006366 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006367 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006368 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006369 }
6370 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006371 (!curproxy->timeout.queue ||
6372 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006373 /* queue timeout not set. We search in the following order:
6374 * default.queue, curr.connect, default.connect.
6375 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006376 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006377 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006378 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006379 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006380 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006381 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006382 }
6383 }
6384
Willy Tarreau1620ec32011-08-06 17:05:02 +02006385 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006386 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6387 curproxy->check_req = (char *)malloc(curproxy->check_len);
6388 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006389 }
6390
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006391 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006392 if (curproxy->nb_req_cap) {
6393 if (curproxy->mode == PR_MODE_HTTP) {
6394 curproxy->req_cap_pool = create_pool("ptrcap",
6395 curproxy->nb_req_cap * sizeof(char *),
6396 MEM_F_SHARED);
6397 } else {
6398 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6399 proxy_type_str(curproxy), curproxy->id);
6400 err_code |= ERR_WARN;
6401 curproxy->to_log &= ~LW_REQHDR;
6402 curproxy->nb_req_cap = 0;
6403 }
6404 }
6405
6406 if (curproxy->nb_rsp_cap) {
6407 if (curproxy->mode == PR_MODE_HTTP) {
6408 curproxy->rsp_cap_pool = create_pool("ptrcap",
6409 curproxy->nb_rsp_cap * sizeof(char *),
6410 MEM_F_SHARED);
6411 } else {
6412 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6413 proxy_type_str(curproxy), curproxy->id);
6414 err_code |= ERR_WARN;
6415 curproxy->to_log &= ~LW_REQHDR;
6416 curproxy->nb_rsp_cap = 0;
6417 }
6418 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006419
Willy Tarreau196729e2012-05-31 19:30:26 +02006420 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006421 if (!(curproxy->cap & PR_CAP_FE)) {
6422 if (curproxy->logformat_string != default_http_log_format &&
6423 curproxy->logformat_string != default_tcp_log_format &&
6424 curproxy->logformat_string != clf_http_log_format)
6425 free(curproxy->logformat_string);
6426 curproxy->logformat_string = NULL;
6427 }
6428
Willy Tarreau196729e2012-05-31 19:30:26 +02006429 if (curproxy->logformat_string)
6430 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6431
6432 if (curproxy->uniqueid_format_string)
6433 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6434
Willy Tarreaubaaee002006-06-26 02:48:02 +02006435 /* first, we will invert the servers list order */
6436 newsrv = NULL;
6437 while (curproxy->srv) {
6438 struct server *next;
6439
6440 next = curproxy->srv->next;
6441 curproxy->srv->next = newsrv;
6442 newsrv = curproxy->srv;
6443 if (!next)
6444 break;
6445 curproxy->srv = next;
6446 }
6447
Willy Tarreaudd701652010-05-25 23:03:02 +02006448 /* assign automatic UIDs to servers which don't have one yet */
6449 next_id = 1;
6450 newsrv = curproxy->srv;
6451 while (newsrv != NULL) {
6452 if (!newsrv->puid) {
6453 /* server ID not set, use automatic numbering with first
6454 * spare entry starting with next_svid.
6455 */
6456 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6457 newsrv->conf.id.key = newsrv->puid = next_id;
6458 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6459 }
6460 next_id++;
6461 newsrv = newsrv->next;
6462 }
6463
Willy Tarreau20697042007-11-15 23:26:18 +01006464 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006465 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006466
Willy Tarreau62c3be22012-01-20 13:12:32 +01006467 /*
6468 * If this server supports a maxconn parameter, it needs a dedicated
6469 * tasks to fill the emptied slots when a connection leaves.
6470 * Also, resolve deferred tracking dependency if needed.
6471 */
6472 newsrv = curproxy->srv;
6473 while (newsrv != NULL) {
6474 if (newsrv->minconn > newsrv->maxconn) {
6475 /* Only 'minconn' was specified, or it was higher than or equal
6476 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6477 * this will avoid further useless expensive computations.
6478 */
6479 newsrv->maxconn = newsrv->minconn;
6480 } else if (newsrv->maxconn && !newsrv->minconn) {
6481 /* minconn was not specified, so we set it to maxconn */
6482 newsrv->minconn = newsrv->maxconn;
6483 }
6484
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006485#ifdef USE_OPENSSL
6486#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6487#define SSL_OP_NO_COMPRESSION 0
6488#endif
6489#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6490#define SSL_MODE_RELEASE_BUFFERS 0
6491#endif
6492#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6493#define SSL_OP_NO_COMPRESSION 0
6494#endif
6495 if (newsrv->use_ssl) {
6496 int ssloptions =
6497 SSL_OP_ALL | /* all known workarounds for bugs */
6498 SSL_OP_NO_SSLv2 |
6499 SSL_OP_NO_COMPRESSION;
6500 int sslmode =
6501 SSL_MODE_ENABLE_PARTIAL_WRITE |
6502 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6503 SSL_MODE_RELEASE_BUFFERS;
6504
6505 /* Initiate SSL context for current server */
6506 newsrv->ssl_ctx.reused_sess = NULL;
6507 newsrv->data = &ssl_sock;
6508 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6509 if(!newsrv->ssl_ctx.ctx) {
6510
6511 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6512 proxy_type_str(curproxy), curproxy->id,
6513 newsrv->id);
6514 cfgerr++;
6515 goto next_srv;
6516 }
6517
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006518 if (newsrv->ssl_ctx.nosslv3)
6519 ssloptions |= SSL_OP_NO_SSLv3;
6520 if (newsrv->ssl_ctx.notlsv1)
6521 ssloptions |= SSL_OP_NO_TLSv1;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006522 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6523 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6524 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6525 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006526 if (newsrv->ssl_ctx.ciphers &&
6527 !SSL_CTX_set_cipher_list(newsrv->ssl_ctx.ctx, newsrv->ssl_ctx.ciphers)) {
6528 Alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
6529 curproxy->id, newsrv->id,
6530 newsrv->conf.file, newsrv->conf.line, newsrv->ssl_ctx.ciphers);
6531 cfgerr++;
6532 goto next_srv;
6533 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006534 }
6535#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006536 if (newsrv->trackit) {
6537 struct proxy *px;
6538 struct server *srv;
6539 char *pname, *sname;
6540
6541 pname = newsrv->trackit;
6542 sname = strrchr(pname, '/');
6543
6544 if (sname)
6545 *sname++ = '\0';
6546 else {
6547 sname = pname;
6548 pname = NULL;
6549 }
6550
6551 if (pname) {
6552 px = findproxy(pname, PR_CAP_BE);
6553 if (!px) {
6554 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6555 proxy_type_str(curproxy), curproxy->id,
6556 newsrv->id, pname);
6557 cfgerr++;
6558 goto next_srv;
6559 }
6560 } else
6561 px = curproxy;
6562
6563 srv = findserver(px, sname);
6564 if (!srv) {
6565 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6566 proxy_type_str(curproxy), curproxy->id,
6567 newsrv->id, sname);
6568 cfgerr++;
6569 goto next_srv;
6570 }
6571
6572 if (!(srv->state & SRV_CHECKED)) {
6573 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6574 "tracking as it does not have checks enabled.\n",
6575 proxy_type_str(curproxy), curproxy->id,
6576 newsrv->id, px->id, srv->id);
6577 cfgerr++;
6578 goto next_srv;
6579 }
6580
6581 if (curproxy != px &&
6582 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6583 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6584 "tracking: disable-on-404 option inconsistency.\n",
6585 proxy_type_str(curproxy), curproxy->id,
6586 newsrv->id, px->id, srv->id);
6587 cfgerr++;
6588 goto next_srv;
6589 }
6590
6591 /* if the other server is forced disabled, we have to do the same here */
6592 if (srv->state & SRV_MAINTAIN) {
6593 newsrv->state |= SRV_MAINTAIN;
6594 newsrv->state &= ~SRV_RUNNING;
6595 newsrv->health = 0;
6596 }
6597
6598 newsrv->track = srv;
6599 newsrv->tracknext = srv->tracknext;
6600 srv->tracknext = newsrv;
6601
6602 free(newsrv->trackit);
6603 newsrv->trackit = NULL;
6604 }
6605 next_srv:
6606 newsrv = newsrv->next;
6607 }
6608
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006609 /* We have to initialize the server lookup mechanism depending
6610 * on what LB algorithm was choosen.
6611 */
6612
6613 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6614 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6615 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006616 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6617 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6618 init_server_map(curproxy);
6619 } else {
6620 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6621 fwrr_init_server_groups(curproxy);
6622 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006623 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006624
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006625 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006626 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6627 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6628 fwlc_init_server_tree(curproxy);
6629 } else {
6630 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6631 fas_init_server_tree(curproxy);
6632 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006633 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006634
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006635 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006636 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6637 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6638 chash_init_server_tree(curproxy);
6639 } else {
6640 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6641 init_server_map(curproxy);
6642 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006643 break;
6644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006645
6646 if (curproxy->options & PR_O_LOGASAP)
6647 curproxy->to_log &= ~LW_BYTES;
6648
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006649 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006650 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006651 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6652 proxy_type_str(curproxy), curproxy->id);
6653 err_code |= ERR_WARN;
6654 }
6655
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006656 if (curproxy->mode != PR_MODE_HTTP) {
6657 int optnum;
6658
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006659 if (curproxy->uri_auth) {
6660 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6661 proxy_type_str(curproxy), curproxy->id);
6662 err_code |= ERR_WARN;
6663 curproxy->uri_auth = NULL;
6664 }
6665
Willy Tarreau87cf5142011-08-19 22:57:24 +02006666 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006667 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6668 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6669 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006670 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006671 }
6672
6673 if (curproxy->options & PR_O_ORGTO) {
6674 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6675 "originalto", proxy_type_str(curproxy), curproxy->id);
6676 err_code |= ERR_WARN;
6677 curproxy->options &= ~PR_O_ORGTO;
6678 }
6679
6680 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6681 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6682 (curproxy->cap & cfg_opts[optnum].cap) &&
6683 (curproxy->options & cfg_opts[optnum].val)) {
6684 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6685 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6686 err_code |= ERR_WARN;
6687 curproxy->options &= ~cfg_opts[optnum].val;
6688 }
6689 }
6690
6691 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6692 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6693 (curproxy->cap & cfg_opts2[optnum].cap) &&
6694 (curproxy->options2 & cfg_opts2[optnum].val)) {
6695 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6696 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6697 err_code |= ERR_WARN;
6698 curproxy->options2 &= ~cfg_opts2[optnum].val;
6699 }
6700 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006701
Willy Tarreauefa5f512010-03-30 20:13:29 +02006702#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006703 if (curproxy->bind_hdr_occ) {
6704 curproxy->bind_hdr_occ = 0;
6705 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6706 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6707 err_code |= ERR_WARN;
6708 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006709#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006710 }
6711
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006713 * ensure that we're not cross-dressing a TCP server into HTTP.
6714 */
6715 newsrv = curproxy->srv;
6716 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006717 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006718 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6719 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006720 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006721 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006722
Willy Tarreau0cec3312011-10-31 13:49:26 +01006723 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6724 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6725 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6726 err_code |= ERR_WARN;
6727 }
6728
Willy Tarreauefa5f512010-03-30 20:13:29 +02006729#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006730 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6731 newsrv->bind_hdr_occ = 0;
6732 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6733 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6734 err_code |= ERR_WARN;
6735 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006736#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006737 newsrv = newsrv->next;
6738 }
6739
Willy Tarreauc1a21672009-08-16 22:37:44 +02006740 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006741 curproxy->accept = frontend_accept;
6742
Willy Tarreauc1a21672009-08-16 22:37:44 +02006743 if (curproxy->tcp_req.inspect_delay ||
6744 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006745 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006746
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006747 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006748 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006749 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006750 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006751
6752 /* both TCP and HTTP must check switching rules */
6753 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6754 }
6755
6756 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006757 if (curproxy->tcp_req.inspect_delay ||
6758 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6759 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6760
Emeric Brun97679e72010-09-23 17:56:44 +02006761 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6762 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6763
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006764 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006765 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006766 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006767 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006768
6769 /* If the backend does requires RDP cookie persistence, we have to
6770 * enable the corresponding analyser.
6771 */
6772 if (curproxy->options2 & PR_O2_RDPC_PRST)
6773 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6774 }
6775
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006776 listener = NULL;
6777 while (curproxy->listen) {
6778 struct listener *next;
6779
6780 next = curproxy->listen->next;
6781 curproxy->listen->next = listener;
6782 listener = curproxy->listen;
6783
6784 if (!next)
6785 break;
6786
6787 curproxy->listen = next;
6788 }
6789
Willy Tarreaue6b98942007-10-29 01:09:36 +01006790 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006791 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006792 listener = curproxy->listen;
6793 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006794 if (!listener->luid) {
6795 /* listener ID not set, use automatic numbering with first
6796 * spare entry starting with next_luid.
6797 */
6798 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6799 listener->conf.id.key = listener->luid = next_id;
6800 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006801 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006802 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006803
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006804 /* enable separate counters */
6805 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6806 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6807 if (!listener->name) {
6808 sprintf(trash, "sock-%d", listener->luid);
6809 listener->name = strdup(trash);
6810 }
6811 }
6812
Emeric Brun6e159292012-05-18 16:32:13 +02006813#ifdef USE_OPENSSL
David BERARDe566ecb2012-09-04 15:15:13 +02006814#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
6815#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
6816#endif
6817
Emeric Brun6e159292012-05-18 16:32:13 +02006818#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6819#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6820#endif
6821#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6822#define SSL_OP_NO_COMPRESSION 0
6823#endif
6824#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6825#define SSL_MODE_RELEASE_BUFFERS 0
6826#endif
6827 /* Initialize SSL */
6828 if (listener->ssl_cert) {
6829 int ssloptions =
6830 SSL_OP_ALL | /* all known workarounds for bugs */
6831 SSL_OP_NO_SSLv2 |
6832 SSL_OP_NO_COMPRESSION |
6833 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6834 int sslmode =
6835 SSL_MODE_ENABLE_PARTIAL_WRITE |
6836 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6837 SSL_MODE_RELEASE_BUFFERS;
6838
6839 listener->data = &ssl_sock; /* data layer */
6840 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6841 if (!listener->ssl_ctx.ctx) {
6842 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6843 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6844 cfgerr++;
6845 goto skip_ssl;
6846 }
Willy Tarreauc230b8b2012-09-03 23:55:16 +02006847 if (listener->ssl_ctx.nosslv3)
6848 ssloptions |= SSL_OP_NO_SSLv3;
6849 if (listener->ssl_ctx.notlsv1)
6850 ssloptions |= SSL_OP_NO_TLSv1;
David BERARDe566ecb2012-09-04 15:15:13 +02006851 if (listener->ssl_ctx.prefer_server_ciphers)
6852 ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
Emeric Brun6e159292012-05-18 16:32:13 +02006853 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6854 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6855 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
Emeric Brunfc32aca2012-09-03 12:10:29 +02006856 if (shared_context_init(global.tune.sslcachesize) < 0) {
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006857 Alert("Unable to allocate SSL session cache.\n");
6858 cfgerr++;
6859 goto skip_ssl;
6860 }
6861 shared_context_set_cache(listener->ssl_ctx.ctx);
Willy Tarreaud7aacbf2012-09-03 23:34:19 +02006862 if (listener->ssl_ctx.ciphers &&
6863 !SSL_CTX_set_cipher_list(listener->ssl_ctx.ctx, listener->ssl_ctx.ciphers)) {
6864 Alert("Proxy '%s': unable to set SSL cipher list to '%s' for listener %d (%s:%d) using cert '%s'.\n",
6865 curproxy->id, listener->ssl_ctx.ciphers, listener->luid,
6866 listener->conf.file, listener->conf.line, listener->ssl_cert);
6867 cfgerr++;
6868 goto skip_ssl;
6869 }
Emeric Brunaa35f1f2012-09-03 11:53:36 +02006870
Emeric Brune1f38db2012-09-03 20:36:47 +02006871 SSL_CTX_set_info_callback(listener->ssl_ctx.ctx, ssl_sock_infocbk);
Emeric Brun6e159292012-05-18 16:32:13 +02006872
6873 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6874 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6875 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6876 cfgerr++;
6877 goto skip_ssl;
6878 }
6879
6880 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6881 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6882 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6883 cfgerr++;
6884 goto skip_ssl;
6885 }
6886 }
6887 skip_ssl:
6888#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006889 if (curproxy->options & PR_O_TCP_NOLING)
6890 listener->options |= LI_O_NOLINGER;
6891 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006892 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006893 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006894 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006895 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006896 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006897 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006898
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006899 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6900 listener->options |= LI_O_TCP_RULES;
6901
Willy Tarreaude3041d2010-05-31 10:56:17 +02006902 if (curproxy->mon_mask.s_addr)
6903 listener->options |= LI_O_CHK_MONNET;
6904
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006905 /* smart accept mode is automatic in HTTP mode */
6906 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreaufbac6632012-09-03 22:33:40 +02006907 ((curproxy->mode == PR_MODE_HTTP || listener->ssl_cert) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006908 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6909 listener->options |= LI_O_NOQUICKACK;
6910
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006911 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006912 listener = listener->next;
6913 }
6914
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006915 /* Check multi-process mode compatibility for the current proxy */
6916 if (global.nbproc > 1) {
6917 int nbproc = 0;
6918 if (curproxy->bind_proc) {
6919 int proc;
6920 for (proc = 0; proc < global.nbproc; proc++) {
6921 if (curproxy->bind_proc & (1 << proc)) {
6922 nbproc++;
6923 }
6924 }
6925 } else {
6926 nbproc = global.nbproc;
6927 }
6928 if (curproxy->table.peers.name) {
6929 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6930 curproxy->id);
6931 cfgerr++;
6932 }
6933 if (nbproc > 1) {
6934 if (curproxy->uri_auth) {
6935 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6936 curproxy->id);
6937 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6938 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6939 curproxy->id);
6940 }
6941 }
6942 if (curproxy->appsession_name) {
6943 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6944 curproxy->id);
6945 }
6946 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6947 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6948 curproxy->id);
6949 }
6950 }
6951 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006952
6953 /* create the task associated with the proxy */
6954 curproxy->task = task_new();
6955 if (curproxy->task) {
6956 curproxy->task->context = curproxy;
6957 curproxy->task->process = manage_proxy;
6958 /* no need to queue, it will be done automatically if some
6959 * listener gets limited.
6960 */
6961 curproxy->task->expire = TICK_ETERNITY;
6962 } else {
6963 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6964 curproxy->id);
6965 cfgerr++;
6966 }
6967
Willy Tarreaubaaee002006-06-26 02:48:02 +02006968 curproxy = curproxy->next;
6969 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006970
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006971 /* Check multi-process mode compatibility */
6972 if (global.nbproc > 1) {
6973 if (global.stats_fe) {
6974 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6975 }
6976 }
6977
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006978 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6979 struct auth_users *curuser;
6980 int g;
6981
6982 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6983 unsigned int group_mask = 0;
6984 char *group = NULL;
6985
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006986 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006987 continue;
6988
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006989 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006990
6991 for (g = 0; g < curuserlist->grpcnt; g++)
6992 if (!strcmp(curuserlist->groups[g], group))
6993 break;
6994
6995 if (g == curuserlist->grpcnt) {
6996 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6997 curuserlist->name, group, curuser->user);
6998 err_code |= ERR_ALERT | ERR_FATAL;
6999 goto out;
7000 }
7001
7002 group_mask |= (1 << g);
7003 }
7004
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007005 free(curuser->u.groups);
7006 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007007 }
7008
7009 for (g = 0; g < curuserlist->grpcnt; g++) {
7010 char *user = NULL;
7011
7012 if (!curuserlist->groupusers[g])
7013 continue;
7014
7015 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7016 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7017 if (!strcmp(curuser->user, user))
7018 break;
7019
7020 if (!curuser) {
7021 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7022 curuserlist->name, user, curuserlist->groups[g]);
7023 err_code |= ERR_ALERT | ERR_FATAL;
7024 goto out;
7025 }
7026
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007027 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007028 }
7029
7030 free(curuserlist->groupusers[g]);
7031 }
7032
7033 free(curuserlist->groupusers);
7034
7035#ifdef DEBUG_AUTH
7036 for (g = 0; g < curuserlist->grpcnt; g++) {
7037 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7038
7039 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007040 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007041 fprintf(stderr, " %s", curuser->user);
7042 }
7043
7044 fprintf(stderr, "\n");
7045 }
7046#endif
7047
Willy Tarreaufbb78422011-06-05 15:38:35 +02007048 }
7049
7050 /* automatically compute fullconn if not set. We must not do it in the
7051 * loop above because cross-references are not yet fully resolved.
7052 */
7053 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7054 /* If <fullconn> is not set, let's set it to 10% of the sum of
7055 * the possible incoming frontend's maxconns.
7056 */
7057 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7058 struct proxy *fe;
7059 int total = 0;
7060
7061 /* sum up the number of maxconns of frontends which
7062 * reference this backend at least once or which are
7063 * the same one ('listen').
7064 */
7065 for (fe = proxy; fe; fe = fe->next) {
7066 struct switching_rule *rule;
7067 struct hdr_exp *exp;
7068 int found = 0;
7069
7070 if (!(fe->cap & PR_CAP_FE))
7071 continue;
7072
7073 if (fe == curproxy) /* we're on a "listen" instance */
7074 found = 1;
7075
7076 if (fe->defbe.be == curproxy) /* "default_backend" */
7077 found = 1;
7078
7079 /* check if a "use_backend" rule matches */
7080 if (!found) {
7081 list_for_each_entry(rule, &fe->switching_rules, list) {
7082 if (rule->be.backend == curproxy) {
7083 found = 1;
7084 break;
7085 }
7086 }
7087 }
7088
7089 /* check if a "reqsetbe" rule matches */
7090 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7091 if (exp->action == ACT_SETBE &&
7092 (struct proxy *)exp->replace == curproxy) {
7093 found = 1;
7094 break;
7095 }
7096 }
7097
7098 /* now we've checked all possible ways to reference a backend
7099 * from a frontend.
7100 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007101 if (!found)
7102 continue;
7103 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007104 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007105 /* we have the sum of the maxconns in <total>. We only
7106 * keep 10% of that sum to set the default fullconn, with
7107 * a hard minimum of 1 (to avoid a divide by zero).
7108 */
7109 curproxy->fullconn = (total + 9) / 10;
7110 if (!curproxy->fullconn)
7111 curproxy->fullconn = 1;
7112 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007113 }
7114
Willy Tarreau056f5682010-06-06 15:51:11 +02007115 /* initialize stick-tables on backend capable proxies. This must not
7116 * be done earlier because the data size may be discovered while parsing
7117 * other proxies.
7118 */
7119 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007120 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007121
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007122 /*
7123 * Recount currently required checks.
7124 */
7125
7126 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7127 int optnum;
7128
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007129 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7130 if (curproxy->options & cfg_opts[optnum].val)
7131 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007132
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007133 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7134 if (curproxy->options2 & cfg_opts2[optnum].val)
7135 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007136 }
7137
Willy Tarreau122541c2011-09-07 21:24:49 +02007138 if (peers) {
7139 struct peers *curpeers = peers, **last;
7140 struct peer *p, *pb;
7141
7142 /* Remove all peers sections which don't have a valid listener.
7143 * This can happen when a peers section is never referenced and
7144 * does not contain a local peer.
7145 */
7146 last = &peers;
7147 while (*last) {
7148 curpeers = *last;
7149 if (curpeers->peers_fe) {
7150 last = &curpeers->next;
7151 continue;
7152 }
7153
7154 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7155 curpeers->id, localpeer);
7156
7157 p = curpeers->remote;
7158 while (p) {
7159 pb = p->next;
7160 free(p->id);
7161 free(p);
7162 p = pb;
7163 }
7164
7165 /* Destroy and unlink this curpeers section.
7166 * Note: curpeers is backed up into *last.
7167 */
7168 free(curpeers->id);
7169 curpeers = curpeers->next;
7170 free(*last);
7171 *last = curpeers;
7172 }
7173 }
7174
Willy Tarreauac1932d2011-10-24 19:14:41 +02007175 if (!global.tune.max_http_hdr)
7176 global.tune.max_http_hdr = MAX_HTTP_HDR;
7177
Willy Tarreau34eb6712011-10-24 18:15:04 +02007178 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007179 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007180 MEM_F_SHARED);
7181
Willy Tarreaubb925012009-07-23 13:36:36 +02007182 if (cfgerr > 0)
7183 err_code |= ERR_ALERT | ERR_FATAL;
7184 out:
7185 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007186}
7187
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007188/*
7189 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7190 * parsing sessions.
7191 */
7192void cfg_register_keywords(struct cfg_kw_list *kwl)
7193{
7194 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7195}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007196
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007197/*
7198 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7199 */
7200void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7201{
7202 LIST_DEL(&kwl->list);
7203 LIST_INIT(&kwl->list);
7204}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007205
7206/*
7207 * Local variables:
7208 * c-indent-level: 8
7209 * c-basic-offset: 8
7210 * End:
7211 */