blob: 06559e6b62596b49cc904a83d275e2d882e2bd08 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020065#include <proto/raw_sock.h>
Emeric Brun6e159292012-05-18 16:32:13 +020066#ifdef USE_OPENSSL
67#include <proto/ssl_sock.h>
68#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010070#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071
72
Willy Tarreauf3c69202006-07-09 16:42:34 +020073/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
74 * ssl-hello-chk option to ensure that the remote server speaks SSL.
75 *
76 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
77 */
78const char sslv3_client_hello_pkt[] = {
79 "\x16" /* ContentType : 0x16 = Hanshake */
80 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
81 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
82 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
83 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
84 "\x03\x00" /* Hello Version : 0x0300 = v3 */
85 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
86 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
87 "\x00" /* Session ID length : empty (no session ID) */
88 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
89 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
90 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
91 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
92 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
93 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
94 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
95 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
96 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
97 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
98 "\x00\x38" "\x00\x39" "\x00\x3A"
99 "\x01" /* Compression Length : 0x01 = 1 byte for types */
100 "\x00" /* Compression Type : 0x00 = NULL compression */
101};
102
Willy Tarreau3842f002009-06-14 11:39:52 +0200103/* various keyword modifiers */
104enum kw_mod {
105 KWM_STD = 0, /* normal */
106 KWM_NO, /* "no" prefixed before the keyword */
107 KWM_DEF, /* "default" prefixed before the keyword */
108};
109
Willy Tarreau13943ab2006-12-31 00:24:10 +0100110/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100112 const char *name;
113 unsigned int val;
114 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100115 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100117};
118
119/* proxy->options */
120static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100121{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100122 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
123 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
124 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
126 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
127 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
128 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
131 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
132 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
134 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
135 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
136 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
137 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100138#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100140#else
141 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100142#endif
143
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100145};
146
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100147/* proxy->options2 */
148static const struct cfg_opt cfg_opts2[] =
149{
150#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
152 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100154#else
155 { "splice-request", 0, 0, 0, 0 },
156 { "splice-response", 0, 0, 0, 0 },
157 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100158#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
160 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
161 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
162 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
163 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
164 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
165 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
167 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400168 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100169 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200170 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200171 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100172 { NULL, 0, 0, 0 }
173};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200174
Willy Tarreau6daf3432008-01-22 16:44:08 +0100175static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
177int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100178int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200180/* List head of all known configuration keywords */
181static struct cfg_kw_list cfg_keywords = {
182 .list = LIST_HEAD_INIT(cfg_keywords.list)
183};
184
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185/*
186 * converts <str> to a list of listeners which are dynamically allocated.
187 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
188 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
189 * - <port> is a numerical port from 1 to 65535 ;
190 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
191 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200192 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200193 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100194static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195{
196 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100197 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 int port, end;
199
200 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200201
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 while (next && *next) {
203 struct sockaddr_storage ss;
204
205 str = next;
206 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100207 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 *next++ = 0;
209 }
210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (*str == '/') {
212 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
213 /* so compute max path */
214 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
215 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 +0200216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100218 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
219 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200220 goto fail;
221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200224 ss.ss_family = AF_UNIX;
225 if (global.unix_bind.prefix) {
226 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
227 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 }
Emeric Bruned760922010-10-22 17:59:25 +0200229 else {
230 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
231 }
232 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
234 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100235 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 ss2 = str2sa_range(str, &port, &end);
238 if (!ss2) {
239 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 if (!port) {
245 Alert("parsing [%s:%d] : missing port number: '%s'\n",
246 file, line, str);
247 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 /* OK the address looks correct */
251 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
258
259 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100260 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
261 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264 }
265
266 for (; port <= end; port++) {
267 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200268 l->next = curproxy->listen;
269 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
271 l->fd = -1;
272 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200273 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
285 l->perm.ux.gid = l->perm.ux.uid = -1;
286 l->perm.ux.mode = 0;
287 uxst_add_listener(l);
288 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200290 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100291 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 } /* end for(port) */
293 } /* end while(next) */
294 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200295 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296 fail:
297 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200298 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299}
300
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301/*
302 * Sends a warning if proxy <proxy> does not have at least one of the
303 * capabilities in <cap>. An optionnal <hint> may be added at the end
304 * of the warning to help the user. Returns 1 if a warning was emitted
305 * or 0 if the condition is valid.
306 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100307int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100308{
309 char *msg;
310
311 switch (cap) {
312 case PR_CAP_BE: msg = "no backend"; break;
313 case PR_CAP_FE: msg = "no frontend"; break;
314 case PR_CAP_RS: msg = "no ruleset"; break;
315 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
316 default: msg = "not enough"; break;
317 }
318
319 if (!(proxy->cap & cap)) {
320 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100321 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100322 return 1;
323 }
324 return 0;
325}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326
Willy Tarreau61d18892009-03-31 10:49:21 +0200327/* Report a warning if a rule is placed after a 'block' rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100330int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200331{
332 if (!LIST_ISEMPTY(&proxy->block_cond)) {
333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a reqrewrite rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100343int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200344{
345 if (proxy->req_exp) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a reqadd rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100356int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200357{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100358 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* Report a warning if a rule is placed after a redirect rule.
367 * Return 1 if the warning has been emitted, otherwise 0.
368 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100369int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200370{
371 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
372 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
373 file, line, arg);
374 return 1;
375 }
376 return 0;
377}
378
379/* Report a warning if a rule is placed after a 'use_backend' rule.
380 * Return 1 if the warning has been emitted, otherwise 0.
381 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100382int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200383{
384 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
385 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
386 file, line, arg);
387 return 1;
388 }
389 return 0;
390}
391
392/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
396 warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
405 warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
409/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100410int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200411{
412 return warnif_rule_after_redirect(proxy, file, line, arg) ||
413 warnif_rule_after_use_backend(proxy, file, line, arg);
414}
415
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100416/* Report it if a request ACL condition uses some response-only parameters. It
417 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
418 * Note that <cond> may be NULL and then will be ignored.
419 */
420static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
421{
422 struct acl *acl;
423
424 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
425 return 0;
426
427 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
428 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
429 file, line, acl ? acl->name : "(unknown)");
430 return ERR_WARN;
431}
432
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100433/* Report it if a request ACL condition uses some request-only volatile parameters.
434 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
435 * Note that <cond> may be NULL and then will be ignored.
436 */
437static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
438{
439 struct acl *acl;
440
441 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
442 return 0;
443
444 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
445 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
446 file, line, acl ? acl->name : "(unknown)");
447 return ERR_WARN;
448}
449
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100450
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200452 * parse a line in a <global> section. Returns the error code, 0 if OK, or
453 * any combination of :
454 * - ERR_ABORT: must abort ASAP
455 * - ERR_FATAL: we can continue parsing but not start the service
456 * - ERR_WARN: a warning has been emitted
457 * - ERR_ALERT: an alert has been emitted
458 * Only the two first ones can stop processing, the two others are just
459 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200461int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462{
Willy Tarreau058e9072009-07-20 09:30:05 +0200463 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200464 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465
466 if (!strcmp(args[0], "global")) { /* new section */
467 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
470 else if (!strcmp(args[0], "daemon")) {
471 global.mode |= MODE_DAEMON;
472 }
473 else if (!strcmp(args[0], "debug")) {
474 global.mode |= MODE_DEBUG;
475 }
476 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200479 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100480 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200481 }
482 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100483 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200484 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100486 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100488 else if (!strcmp(args[0], "nosplice")) {
489 global.tune.options &= ~GTUNE_USE_SPLICE;
490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491 else if (!strcmp(args[0], "quiet")) {
492 global.mode |= MODE_QUIET;
493 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 else if (!strcmp(args[0], "tune.maxpollevents")) {
495 if (global.tune.maxpollevents != 0) {
496 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200497 err_code |= ERR_ALERT;
498 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200499 }
500 if (*(args[1]) == 0) {
501 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200504 }
505 global.tune.maxpollevents = atol(args[1]);
506 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 else if (!strcmp(args[0], "tune.maxaccept")) {
508 if (global.tune.maxaccept != 0) {
509 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200510 err_code |= ERR_ALERT;
511 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100512 }
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100517 }
518 global.tune.maxaccept = atol(args[1]);
519 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200520 else if (!strcmp(args[0], "tune.chksize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.chksize = atol(args[1]);
527 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200528 else if (!strcmp(args[0], "tune.bufsize")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.bufsize = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200537 trashlen = global.tune.bufsize;
538 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 }
540 else if (!strcmp(args[0], "tune.maxrewrite")) {
541 if (*(args[1]) == 0) {
542 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT | ERR_FATAL;
544 goto out;
545 }
546 global.tune.maxrewrite = atol(args[1]);
547 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
548 global.tune.maxrewrite = global.tune.bufsize / 2;
549 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100550 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
551 if (global.tune.client_rcvbuf != 0) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.tune.client_rcvbuf = atol(args[1]);
562 }
563 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
564 if (global.tune.server_rcvbuf != 0) {
565 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT;
567 goto out;
568 }
569 if (*(args[1]) == 0) {
570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
573 }
574 global.tune.server_rcvbuf = atol(args[1]);
575 }
576 else if (!strcmp(args[0], "tune.sndbuf.client")) {
577 if (global.tune.client_sndbuf != 0) {
578 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT;
580 goto out;
581 }
582 if (*(args[1]) == 0) {
583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587 global.tune.client_sndbuf = atol(args[1]);
588 }
589 else if (!strcmp(args[0], "tune.sndbuf.server")) {
590 if (global.tune.server_sndbuf != 0) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.server_sndbuf = atol(args[1]);
601 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200602 else if (!strcmp(args[0], "tune.pipesize")) {
603 if (*(args[1]) == 0) {
604 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
605 err_code |= ERR_ALERT | ERR_FATAL;
606 goto out;
607 }
608 global.tune.pipesize = atol(args[1]);
609 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200610 else if (!strcmp(args[0], "tune.http.maxhdr")) {
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
615 }
616 global.tune.max_http_hdr = atol(args[1]);
617 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 else if (!strcmp(args[0], "uid")) {
619 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 }
624 if (*(args[1]) == 0) {
625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200626 err_code |= ERR_ALERT | ERR_FATAL;
627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 }
629 global.uid = atol(args[1]);
630 }
631 else if (!strcmp(args[0], "gid")) {
632 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200634 err_code |= ERR_ALERT;
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 }
637 if (*(args[1]) == 0) {
638 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200641 }
642 global.gid = atol(args[1]);
643 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200644 /* user/group name handling */
645 else if (!strcmp(args[0], "user")) {
646 struct passwd *ha_user;
647 if (global.uid != 0) {
648 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200649 err_code |= ERR_ALERT;
650 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200651 }
652 errno = 0;
653 ha_user = getpwnam(args[1]);
654 if (ha_user != NULL) {
655 global.uid = (int)ha_user->pw_uid;
656 }
657 else {
658 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 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200660 }
661 }
662 else if (!strcmp(args[0], "group")) {
663 struct group *ha_group;
664 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200665 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200666 err_code |= ERR_ALERT;
667 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200668 }
669 errno = 0;
670 ha_group = getgrnam(args[1]);
671 if (ha_group != NULL) {
672 global.gid = (int)ha_group->gr_gid;
673 }
674 else {
675 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 +0200676 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200677 }
678 }
679 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 else if (!strcmp(args[0], "nbproc")) {
681 if (global.nbproc != 0) {
682 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200683 err_code |= ERR_ALERT;
684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200685 }
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691 global.nbproc = atol(args[1]);
692 }
693 else if (!strcmp(args[0], "maxconn")) {
694 if (global.maxconn != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200696 err_code |= ERR_ALERT;
697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 global.maxconn = atol(args[1]);
705#ifdef SYSTEM_MAXCONN
706 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
707 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);
708 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 }
711#endif /* SYSTEM_MAXCONN */
712 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200713 else if (!strcmp(args[0], "maxconnrate")) {
714 if (global.cps_lim != 0) {
715 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT;
717 goto out;
718 }
719 if (*(args[1]) == 0) {
720 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
721 err_code |= ERR_ALERT | ERR_FATAL;
722 goto out;
723 }
724 global.cps_lim = atol(args[1]);
725 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 else if (!strcmp(args[0], "maxpipes")) {
727 if (global.maxpipes != 0) {
728 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT;
730 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100731 }
732 if (*(args[1]) == 0) {
733 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100736 }
737 global.maxpipes = atol(args[1]);
738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 else if (!strcmp(args[0], "ulimit-n")) {
740 if (global.rlimit_nofile != 0) {
741 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200742 err_code |= ERR_ALERT;
743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 }
745 if (*(args[1]) == 0) {
746 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 global.rlimit_nofile = atol(args[1]);
751 }
752 else if (!strcmp(args[0], "chroot")) {
753 if (global.chroot != NULL) {
754 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT;
756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 }
758 if (*(args[1]) == 0) {
759 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT | ERR_FATAL;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 global.chroot = strdup(args[1]);
764 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200765 else if (!strcmp(args[0], "description")) {
766 int i, len=0;
767 char *d;
768
769 if (!*args[1]) {
770 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775
776 for(i=1; *args[i]; i++)
777 len += strlen(args[i])+1;
778
779 if (global.desc)
780 free(global.desc);
781
782 global.desc = d = (char *)calloc(1, len);
783
784 d += sprintf(d, "%s", args[1]);
785 for(i=2; *args[i]; i++)
786 d += sprintf(d, " %s", args[i]);
787 }
788 else if (!strcmp(args[0], "node")) {
789 int i;
790 char c;
791
792 for (i=0; args[1][i]; i++) {
793 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100794 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
795 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200796 break;
797 }
798
799 if (!i || args[1][i]) {
800 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
801 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
802 file, linenum, args[0]);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806
807 if (global.node)
808 free(global.node);
809
810 global.node = strdup(args[1]);
811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 else if (!strcmp(args[0], "pidfile")) {
813 if (global.pidfile != NULL) {
814 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200815 err_code |= ERR_ALERT;
816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200817 }
818 if (*(args[1]) == 0) {
819 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200822 }
823 global.pidfile = strdup(args[1]);
824 }
Emeric Bruned760922010-10-22 17:59:25 +0200825 else if (!strcmp(args[0], "unix-bind")) {
826 int cur_arg = 1;
827 while (*(args[cur_arg])) {
828 if (!strcmp(args[cur_arg], "prefix")) {
829 if (global.unix_bind.prefix != NULL) {
830 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
831 err_code |= ERR_ALERT;
832 cur_arg += 2;
833 continue;
834 }
835
836 if (*(args[cur_arg+1]) == 0) {
837 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.unix_bind.prefix = strdup(args[cur_arg+1]);
842 cur_arg += 2;
843 continue;
844 }
845
846 if (!strcmp(args[cur_arg], "mode")) {
847
848 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
849 cur_arg += 2;
850 continue;
851 }
852
853 if (!strcmp(args[cur_arg], "uid")) {
854
855 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
856 cur_arg += 2;
857 continue;
858 }
859
860 if (!strcmp(args[cur_arg], "gid")) {
861
862 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
863 cur_arg += 2;
864 continue;
865 }
866
867 if (!strcmp(args[cur_arg], "user")) {
868 struct passwd *user;
869
870 user = getpwnam(args[cur_arg + 1]);
871 if (!user) {
872 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
873 file, linenum, args[0], args[cur_arg + 1 ]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 global.unix_bind.ux.uid = user->pw_uid;
879 cur_arg += 2;
880 continue;
881 }
882
883 if (!strcmp(args[cur_arg], "group")) {
884 struct group *group;
885
886 group = getgrnam(args[cur_arg + 1]);
887 if (!group) {
888 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
889 file, linenum, args[0], args[cur_arg + 1 ]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893
894 global.unix_bind.ux.gid = group->gr_gid;
895 cur_arg += 2;
896 continue;
897 }
898
Willy Tarreaub48f9582011-09-05 01:17:06 +0200899 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200900 file, linenum, args[0]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904 }
William Lallemand0f99e342011-10-12 17:50:54 +0200905 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
906 /* delete previous herited or defined syslog servers */
907 struct logsrv *back;
908 struct logsrv *tmp;
909
910 if (*(args[1]) != 0) {
911 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914 }
915
916 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
917 LIST_DEL(&tmp->list);
918 free(tmp);
919 }
920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200922 struct logsrv *logsrv;
923
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 if (*(args[1]) == 0 || *(args[2]) == 0) {
925 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 }
William Lallemand0f99e342011-10-12 17:50:54 +0200929
930 logsrv = calloc(1, sizeof(struct logsrv));
931
932 logsrv->facility = get_log_facility(args[2]);
933 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->level = get_log_level(args[3]);
942 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 }
948
William Lallemand0f99e342011-10-12 17:50:54 +0200949 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200950 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200951 logsrv->minlvl = get_log_level(args[4]);
952 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200953 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 }
957 }
958
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 if (!sk) {
962 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100963 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200965 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100966 goto out;
967 }
William Lallemand0f99e342011-10-12 17:50:54 +0200968 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100969 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100970 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100971 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100972 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
973 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200974 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100975 goto out;
976 }
William Lallemand0f99e342011-10-12 17:50:54 +0200977 logsrv->addr = *sk;
978 if (!get_host_port(&logsrv->addr))
979 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981
William Lallemand0f99e342011-10-12 17:50:54 +0200982 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200983 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100984 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
985 char *name;
986 int len;
987
988 if (global.log_send_hostname != NULL) {
989 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
990 err_code |= ERR_ALERT;
991 goto out;
992 }
993
994 if (*(args[1]))
995 name = args[1];
996 else
997 name = hostname;
998
999 len = strlen(name);
1000
1001 /* We'll add a space after the name to respect the log format */
1002 free(global.log_send_hostname);
1003 global.log_send_hostname = malloc(len + 2);
1004 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1005 }
Kevinm48936af2010-12-22 16:08:21 +00001006 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 free(global.log_tag);
1013 global.log_tag = strdup(args[1]);
1014 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1016 if (global.spread_checks != 0) {
1017 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT;
1019 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
1021 if (*(args[1]) == 0) {
1022 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001025 }
1026 global.spread_checks = atol(args[1]);
1027 if (global.spread_checks < 0 || global.spread_checks > 50) {
1028 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001031 }
1032 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001033 struct cfg_kw_list *kwl;
1034 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001036
1037 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1038 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1039 if (kwl->kw[index].section != CFG_GLOBAL)
1040 continue;
1041 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1042 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001043 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001044 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001045 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001047 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001049 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001050 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001051 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 err_code |= ERR_WARN;
1053 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001054 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001055 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001056 }
1057 }
1058 }
1059
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001062 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001063
Willy Tarreau058e9072009-07-20 09:30:05 +02001064 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001065 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067}
1068
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001069void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001071 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 defproxy.mode = PR_MODE_TCP;
1073 defproxy.state = PR_STNEW;
1074 defproxy.maxconn = cfg_maxpconn;
1075 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001076
1077 defproxy.defsrv.inter = DEF_CHKINTR;
1078 defproxy.defsrv.fastinter = 0;
1079 defproxy.defsrv.downinter = 0;
1080 defproxy.defsrv.rise = DEF_RISETIME;
1081 defproxy.defsrv.fall = DEF_FALLTIME;
1082 defproxy.defsrv.check_port = 0;
1083 defproxy.defsrv.maxqueue = 0;
1084 defproxy.defsrv.minconn = 0;
1085 defproxy.defsrv.maxconn = 0;
1086 defproxy.defsrv.slowstart = 0;
1087 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1088 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1089 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001090}
1091
Willy Tarreauade5ec42010-01-28 19:33:49 +01001092
1093static int create_cond_regex_rule(const char *file, int line,
1094 struct proxy *px, int dir, int action, int flags,
1095 const char *cmd, const char *reg, const char *repl,
1096 const char **cond_start)
1097{
1098 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001099 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001100 const char *err;
1101 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001102 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001103
1104 if (px == &defproxy) {
1105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto err;
1108 }
1109
1110 if (*reg == 0) {
1111 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1117 err_code |= ERR_WARN;
1118
Willy Tarreau5321c422010-01-28 20:35:13 +01001119 if (cond_start &&
1120 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001121 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1122 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1123 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001124 err_code |= ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127 }
1128 else if (cond_start && **cond_start) {
1129 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1130 file, line, cmd, *cond_start);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto err;
1133 }
1134
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001135 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001136 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001137 else
1138 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001139
Willy Tarreauade5ec42010-01-28 19:33:49 +01001140 preg = calloc(1, sizeof(regex_t));
1141 if (!preg) {
1142 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1143 err_code = ERR_ALERT | ERR_FATAL;
1144 goto err;
1145 }
1146
1147 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1148 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1149 err_code = ERR_ALERT | ERR_FATAL;
1150 goto err;
1151 }
1152
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001153 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001154 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001155 if (repl && err) {
1156 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1157 file, line, cmd, *err);
1158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto err;
1160 }
1161
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001162 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001163 err_code |= ERR_WARN;
1164
Willy Tarreauf4068b62012-05-08 17:37:49 +02001165 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 return err_code;
1167 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001168 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001169 free(preg);
1170 return err_code;
1171}
1172
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001174 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001175 * Returns the error code, 0 if OK, or any combination of :
1176 * - ERR_ABORT: must abort ASAP
1177 * - ERR_FATAL: we can continue parsing but not start the service
1178 * - ERR_WARN: a warning has been emitted
1179 * - ERR_ALERT: an alert has been emitted
1180 * Only the two first ones can stop processing, the two others are just
1181 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001183int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1184{
1185 static struct peers *curpeers = NULL;
1186 struct peer *newpeer = NULL;
1187 const char *err;
1188 int err_code = 0;
1189
1190 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1191
1192 err = invalid_char(args[1]);
1193 if (err) {
1194 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1195 file, linenum, *err, args[0], args[1]);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 }
1198
1199 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1200 /*
1201 * If there are two proxies with the same name only following
1202 * combinations are allowed:
1203 */
1204 if (strcmp(curpeers->id, args[1]) == 0) {
1205 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1206 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1207 err_code |= ERR_WARN;
1208 }
1209 }
1210
1211 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1212 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1213 err_code |= ERR_ALERT | ERR_ABORT;
1214 goto out;
1215 }
1216
1217 curpeers->next = peers;
1218 peers = curpeers;
1219 curpeers->conf.file = file;
1220 curpeers->conf.line = linenum;
1221 curpeers->last_change = now.tv_sec;
1222 curpeers->id = strdup(args[1]);
1223 }
1224 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1225 char *rport, *raddr;
1226 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001227 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001228
1229 if (!*args[2]) {
1230 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1231 file, linenum, args[0]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 err = invalid_char(args[1]);
1237 if (err) {
1238 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1239 file, linenum, *err, args[1]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243
1244 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1245 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1246 err_code |= ERR_ALERT | ERR_ABORT;
1247 goto out;
1248 }
1249
1250 /* the peers are linked backwards first */
1251 curpeers->count++;
1252 newpeer->next = curpeers->remote;
1253 curpeers->remote = newpeer;
1254 newpeer->peers = curpeers;
1255 newpeer->conf.file = file;
1256 newpeer->conf.line = linenum;
1257
1258 newpeer->last_change = now.tv_sec;
1259 newpeer->id = strdup(args[1]);
1260
1261 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001262 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001263 if (rport) {
1264 *rport++ = 0;
1265 realport = atol(rport);
1266 }
1267 if (!realport) {
1268 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272
Willy Tarreaufab5a432011-03-04 15:31:53 +01001273 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001274 free(raddr);
1275 if (!sk) {
1276 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1277 err_code |= ERR_ALERT | ERR_FATAL;
1278 goto out;
1279 }
1280 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001281 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001282 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001283 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001284
1285 if (!sk) {
1286 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1287 file, linenum, newpeer->addr.ss_family, args[2]);
1288 err_code |= ERR_ALERT | ERR_FATAL;
1289 goto out;
1290 }
1291
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001292 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001293
1294 if (strcmp(newpeer->id, localpeer) == 0) {
1295 /* Current is local peer, it define a frontend */
1296 newpeer->local = 1;
1297
1298 if (!curpeers->peers_fe) {
1299 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1300 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1301 err_code |= ERR_ALERT | ERR_ABORT;
1302 goto out;
1303 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001304
Willy Tarreau237250c2011-07-29 01:49:03 +02001305 init_new_proxy(curpeers->peers_fe);
1306 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001307
1308 curpeers->peers_fe->last_change = now.tv_sec;
1309 curpeers->peers_fe->id = strdup(args[1]);
1310 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001311 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001312 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1313 curpeers->peers_fe->timeout.connect = 5000;
1314 curpeers->peers_fe->accept = peer_accept;
1315 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001316 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001317 err_code |= ERR_FATAL;
1318 goto out;
1319 }
1320 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1321 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1322 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1323 curpeers->peers_fe->listen->accept = session_accept;
1324 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1325 curpeers->peers_fe->listen->handler = process_session;
1326 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001327 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1328 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001329 }
1330 }
1331 } /* neither "peer" nor "peers" */
1332 else if (*args[0] != 0) {
1333 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
1337
1338out:
1339 return err_code;
1340}
1341
1342
Willy Tarreau3842f002009-06-14 11:39:52 +02001343int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344{
1345 static struct proxy *curproxy = NULL;
1346 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001347 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001348 int rc;
1349 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001350 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001351 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001352 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001353 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354
Willy Tarreau977b8e42006-12-29 14:19:17 +01001355 if (!strcmp(args[0], "listen"))
1356 rc = PR_CAP_LISTEN;
1357 else if (!strcmp(args[0], "frontend"))
1358 rc = PR_CAP_FE | PR_CAP_RS;
1359 else if (!strcmp(args[0], "backend"))
1360 rc = PR_CAP_BE | PR_CAP_RS;
1361 else if (!strcmp(args[0], "ruleset"))
1362 rc = PR_CAP_RS;
1363 else
1364 rc = PR_CAP_NONE;
1365
1366 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 if (!*args[1]) {
1368 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1369 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001371 err_code |= ERR_ALERT | ERR_ABORT;
1372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001374
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001375 err = invalid_char(args[1]);
1376 if (err) {
1377 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1378 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001380 }
1381
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001382 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1383 /*
1384 * If there are two proxies with the same name only following
1385 * combinations are allowed:
1386 *
1387 * listen backend frontend ruleset
1388 * listen - - - -
1389 * backend - - OK -
1390 * frontend - OK - -
1391 * ruleset - - - -
1392 */
1393
1394 if (!strcmp(curproxy->id, args[1]) &&
1395 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1396 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001397 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1398 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1399 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001400 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001401 }
1402 }
1403
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_ALERT | ERR_ABORT;
1407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001409
Willy Tarreau97cb7802010-01-03 20:23:58 +01001410 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001411 curproxy->next = proxy;
1412 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 curproxy->conf.file = file;
1414 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001415 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
1419 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001421 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001422 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001423 err_code |= ERR_FATAL;
1424 goto out;
1425 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001426 new = curproxy->listen;
1427 while (new != last) {
1428 new->conf.file = file;
1429 new->conf.line = linenum;
1430 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001431 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433 }
1434
1435 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001436 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001437 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001438
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001441 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001442 curproxy->no_options = defproxy.no_options;
1443 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001444 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001445 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001446 curproxy->except_net = defproxy.except_net;
1447 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001448 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001449 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001451 if (defproxy.fwdfor_hdr_len) {
1452 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1453 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1454 }
1455
Willy Tarreaub86db342009-11-30 11:50:16 +01001456 if (defproxy.orgto_hdr_len) {
1457 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1458 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1459 }
1460
Mark Lamourinec2247f02012-01-04 13:02:01 -05001461 if (defproxy.server_id_hdr_len) {
1462 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1463 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1464 }
1465
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466 if (curproxy->cap & PR_CAP_FE) {
1467 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001468 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001469 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470
1471 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001472 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1473 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474
1475 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau977b8e42006-12-29 14:19:17 +01001478 if (curproxy->cap & PR_CAP_BE) {
1479 curproxy->fullconn = defproxy.fullconn;
1480 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001482 if (defproxy.check_req) {
1483 curproxy->check_req = calloc(1, defproxy.check_len);
1484 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1485 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001486 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001488 if (defproxy.expect_str) {
1489 curproxy->expect_str = strdup(defproxy.expect_str);
1490 if (defproxy.expect_regex) {
1491 /* note: this regex is known to be valid */
1492 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1493 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1494 }
1495 }
1496
Willy Tarreau67402132012-05-31 20:40:20 +02001497 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498 if (defproxy.cookie_name)
1499 curproxy->cookie_name = strdup(defproxy.cookie_name);
1500 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001501 if (defproxy.cookie_domain)
1502 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001503
Willy Tarreau31936852010-10-06 16:59:56 +02001504 if (defproxy.cookie_maxidle)
1505 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1506
1507 if (defproxy.cookie_maxlife)
1508 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1509
Emeric Brun647caf12009-06-30 17:57:00 +02001510 if (defproxy.rdp_cookie_name)
1511 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1512 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1513
Willy Tarreau01732802007-11-01 22:48:15 +01001514 if (defproxy.url_param_name)
1515 curproxy->url_param_name = strdup(defproxy.url_param_name);
1516 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001517
Benoitaffb4812009-03-25 13:02:10 +01001518 if (defproxy.hh_name)
1519 curproxy->hh_name = strdup(defproxy.hh_name);
1520 curproxy->hh_len = defproxy.hh_len;
1521 curproxy->hh_match_domain = defproxy.hh_match_domain;
1522
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001523 if (defproxy.iface_name)
1524 curproxy->iface_name = strdup(defproxy.iface_name);
1525 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001528 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001529 if (defproxy.capture_name)
1530 curproxy->capture_name = strdup(defproxy.capture_name);
1531 curproxy->capture_namelen = defproxy.capture_namelen;
1532 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001536 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001537 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001538 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001539 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001540 curproxy->uri_auth = defproxy.uri_auth;
1541 curproxy->mon_net = defproxy.mon_net;
1542 curproxy->mon_mask = defproxy.mon_mask;
1543 if (defproxy.monitor_uri)
1544 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1545 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001546 if (defproxy.defbe.name)
1547 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001548
1549 /* get either a pointer to the logformat string or a copy of it */
1550 curproxy->logformat_string = defproxy.logformat_string;
1551 if (curproxy->logformat_string &&
1552 curproxy->logformat_string != default_http_log_format &&
1553 curproxy->logformat_string != default_tcp_log_format &&
1554 curproxy->logformat_string != clf_http_log_format)
1555 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001556 }
1557
1558 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001559 curproxy->timeout.connect = defproxy.timeout.connect;
1560 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001561 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001562 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001563 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001564 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001565 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001566 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 curproxy->source_addr = defproxy.source_addr;
1568 }
1569
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001571
1572 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001573 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001574 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001575 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001576 LIST_INIT(&node->list);
1577 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1578 }
1579
Willy Tarreau196729e2012-05-31 19:30:26 +02001580 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1581 if (curproxy->uniqueid_format_string)
1582 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001583
1584 /* copy default header unique id */
1585 if (defproxy.header_unique_id)
1586 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1587
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001589 curproxy->conf.used_listener_id = EB_ROOT;
1590 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001591
Willy Tarreau93893792009-07-23 13:19:11 +02001592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 }
1594 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1595 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001596 /* FIXME-20070101: we should do this too at the end of the
1597 * config parsing to free all default values.
1598 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(defproxy.check_req);
1600 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001601 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001602 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001603 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001604 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001605 free(defproxy.capture_name);
1606 free(defproxy.monitor_uri);
1607 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001608 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001609 free(defproxy.fwdfor_hdr_name);
1610 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001611 free(defproxy.orgto_hdr_name);
1612 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001613 free(defproxy.server_id_hdr_name);
1614 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001615 free(defproxy.expect_str);
1616 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001617
Willy Tarreau39b06652012-06-01 10:58:06 +02001618 if (defproxy.logformat_string != default_http_log_format &&
1619 defproxy.logformat_string != default_tcp_log_format &&
1620 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001621 free(defproxy.logformat_string);
1622
1623 free(defproxy.uniqueid_format_string);
1624
Willy Tarreaua534fea2008-08-03 12:19:50 +02001625 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001626 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001627
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628 /* we cannot free uri_auth because it might already be used */
1629 init_default_instance();
1630 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001631 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 }
1634 else if (curproxy == NULL) {
1635 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 }
1639
Willy Tarreau977b8e42006-12-29 14:19:17 +01001640
1641 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001643 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001644 int cur_arg;
1645
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 if (curproxy == &defproxy) {
1647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653
Emeric Bruned760922010-10-22 17:59:25 +02001654 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001655 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001660
1661 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001662
1663 /* NOTE: the following line might create several listeners if there
1664 * are comma-separated IPs or port ranges. So all further processing
1665 * will have to be applied to all listeners created after last_listen.
1666 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001667 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
1670 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001671
Willy Tarreau90a570f2009-10-04 20:54:54 +02001672 new_listen = curproxy->listen;
1673 while (new_listen != last_listen) {
1674 new_listen->conf.file = file;
1675 new_listen->conf.line = linenum;
1676 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001677 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001678 }
1679
Emeric Bruned760922010-10-22 17:59:25 +02001680 /* Set default global rights and owner for unix bind */
1681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1683 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001684 cur_arg = 2;
1685 while (*(args[cur_arg])) {
1686 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1687#ifdef SO_BINDTODEVICE
1688 struct listener *l;
1689
Emeric Bruned760922010-10-22 17:59:25 +02001690 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1691 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1692 file, linenum, args[0], args[cur_arg]);
1693 err_code |= ERR_ALERT | ERR_FATAL;
1694 goto out;
1695 }
1696
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001697 if (!*args[cur_arg + 1]) {
1698 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1699 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001700 err_code |= ERR_ALERT | ERR_FATAL;
1701 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001702 }
1703
1704 for (l = curproxy->listen; l != last_listen; l = l->next)
1705 l->interface = strdup(args[cur_arg + 1]);
1706
1707 global.last_checks |= LSTCHK_NETADM;
1708
1709 cur_arg += 2;
1710 continue;
1711#else
1712 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1713 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001714 err_code |= ERR_ALERT | ERR_FATAL;
1715 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001716#endif
1717 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001718 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1719#ifdef TCP_MAXSEG
1720 struct listener *l;
1721 int mss;
1722
Emeric Bruned760922010-10-22 17:59:25 +02001723 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1724 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1725 file, linenum, args[0], args[cur_arg]);
1726 err_code |= ERR_ALERT | ERR_FATAL;
1727 goto out;
1728 }
1729
Willy Tarreaube1b9182009-06-14 18:48:19 +02001730 if (!*args[cur_arg + 1]) {
1731 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1732 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001735 }
1736
Willy Tarreau48a7e722010-12-24 15:26:39 +01001737 mss = atoi(args[cur_arg + 1]);
1738 if (!mss || abs(mss) > 65535) {
1739 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001741 err_code |= ERR_ALERT | ERR_FATAL;
1742 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001743 }
1744
1745 for (l = curproxy->listen; l != last_listen; l = l->next)
1746 l->maxseg = mss;
1747
1748 cur_arg += 2;
1749 continue;
1750#else
1751 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1752 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001755#endif
1756 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001757
1758 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1759#ifdef TCP_DEFER_ACCEPT
1760 struct listener *l;
1761
1762 for (l = curproxy->listen; l != last_listen; l = l->next)
1763 l->options |= LI_O_DEF_ACCEPT;
1764
1765 cur_arg ++;
1766 continue;
1767#else
1768 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1769 file, linenum, args[0], args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772#endif
1773 }
1774
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001775 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001776#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001777 struct listener *l;
1778
Emeric Bruned760922010-10-22 17:59:25 +02001779 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1780 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1781 file, linenum, args[0], args[cur_arg]);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001786 for (l = curproxy->listen; l != last_listen; l = l->next)
1787 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001788
1789 cur_arg ++;
1790 continue;
1791#else
1792 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1793 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001796#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001797 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798
Emeric Brun6e159292012-05-18 16:32:13 +02001799 if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
1800#ifdef USE_OPENSSL
1801 struct listener *l;
1802
1803 if (!*args[cur_arg + 1]) {
1804 Alert("parsing [%s:%d] : '%s' : missing certificate.\n",
1805 file, linenum, args[0]);
1806 err_code |= ERR_ALERT | ERR_FATAL;
1807 goto out;
1808 }
1809
1810 for (l = curproxy->listen; l != last_listen; l = l->next)
1811 l->ssl_cert = strdup(args[cur_arg + 1]);
1812
1813 cur_arg += 2;
1814 continue;
1815#else
1816 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1817 file, linenum, args[0], args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820#endif
1821 }
1822
Willy Tarreau8a956912010-10-15 14:27:08 +02001823 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1824 struct listener *l;
1825
1826 for (l = curproxy->listen; l != last_listen; l = l->next)
1827 l->options |= LI_O_ACC_PROXY;
1828
1829 cur_arg ++;
1830 continue;
1831 }
1832
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001833 if (!strcmp(args[cur_arg], "name")) {
1834 struct listener *l;
1835
1836 for (l = curproxy->listen; l != last_listen; l = l->next)
1837 l->name = strdup(args[cur_arg + 1]);
1838
1839 cur_arg += 2;
1840 continue;
1841 }
1842
1843 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001844 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001845 struct listener *l;
1846
1847 if (curproxy->listen->next != last_listen) {
1848 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1849 file, linenum, args[cur_arg]);
1850 err_code |= ERR_ALERT | ERR_FATAL;
1851 goto out;
1852 }
1853
1854 if (!*args[cur_arg + 1]) {
1855 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1856 file, linenum, args[cur_arg]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859 }
1860
1861 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001862 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001863
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001864 if (curproxy->listen->luid <= 0) {
1865 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001866 file, linenum);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001871 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1872 if (node) {
1873 l = container_of(node, struct listener, conf.id);
1874 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1875 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1880
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001881 cur_arg += 2;
1882 continue;
1883 }
1884
Emeric Bruned760922010-10-22 17:59:25 +02001885 if (!strcmp(args[cur_arg], "mode")) {
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893
1894 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1895
1896 cur_arg += 2;
1897 continue;
1898 }
1899
1900 if (!strcmp(args[cur_arg], "uid")) {
1901
1902 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1903 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1904 file, linenum, args[0], args[cur_arg]);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908
1909 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1910 cur_arg += 2;
1911 continue;
1912 }
1913
1914 if (!strcmp(args[cur_arg], "gid")) {
1915
1916 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1917 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1918 file, linenum, args[0], args[cur_arg]);
1919 err_code |= ERR_ALERT | ERR_FATAL;
1920 goto out;
1921 }
1922
1923 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1924 cur_arg += 2;
1925 continue;
1926 }
1927
1928 if (!strcmp(args[cur_arg], "user")) {
1929 struct passwd *user;
1930
1931 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1932 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1933 file, linenum, args[0], args[cur_arg]);
1934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
1936 }
1937 user = getpwnam(args[cur_arg + 1]);
1938 if (!user) {
1939 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1940 file, linenum, args[0], args[cur_arg + 1 ]);
1941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
1943 }
1944
1945 curproxy->listen->perm.ux.uid = user->pw_uid;
1946 cur_arg += 2;
1947 continue;
1948 }
1949
1950 if (!strcmp(args[cur_arg], "group")) {
1951 struct group *group;
1952
1953 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1954 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1955 file, linenum, args[0], args[cur_arg]);
1956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
1958 }
1959 group = getgrnam(args[cur_arg + 1]);
1960 if (!group) {
1961 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1962 file, linenum, args[0], args[cur_arg + 1 ]);
1963 err_code |= ERR_ALERT | ERR_FATAL;
1964 goto out;
1965 }
1966
1967 curproxy->listen->perm.ux.gid = group->gr_gid;
1968 cur_arg += 2;
1969 continue;
1970 }
1971
Willy Tarreaub48f9582011-09-05 01:17:06 +02001972 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 +01001973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001976 }
Willy Tarreau93893792009-07-23 13:19:11 +02001977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 }
1979 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1980 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1981 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1982 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_ALERT | ERR_FATAL;
1984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001986 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988
Willy Tarreaubaaee002006-06-26 02:48:02 +02001989 /* flush useless bits */
1990 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001993 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001994 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996
Willy Tarreau1c47f852006-07-09 08:22:27 +02001997 if (!*args[1]) {
1998 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002002 }
2003
Willy Tarreaua534fea2008-08-03 12:19:50 +02002004 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002005 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002006 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002007 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002008 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2009
Willy Tarreau93893792009-07-23 13:19:11 +02002010 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2013 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2014 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2015 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2016 else {
2017 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 }
2021 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002022 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002023 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002024
2025 if (curproxy == &defproxy) {
2026 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002030 }
2031
2032 if (!*args[1]) {
2033 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002037 }
2038
2039 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002040 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002041
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002042 if (curproxy->uuid <= 0) {
2043 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002044 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002047 }
2048
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002049 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2050 if (node) {
2051 struct proxy *target = container_of(node, struct proxy, conf.id);
2052 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2053 file, linenum, proxy_type_str(curproxy), curproxy->id,
2054 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
2058 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002059 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002060 else if (!strcmp(args[0], "description")) {
2061 int i, len=0;
2062 char *d;
2063
Cyril Bonté99ed3272010-01-24 23:29:44 +01002064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2066 file, linenum, args[0]);
2067 err_code |= ERR_ALERT | ERR_FATAL;
2068 goto out;
2069 }
2070
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002071 if (!*args[1]) {
2072 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2073 file, linenum, args[0]);
2074 return -1;
2075 }
2076
2077 for(i=1; *args[i]; i++)
2078 len += strlen(args[i])+1;
2079
2080 d = (char *)calloc(1, len);
2081 curproxy->desc = d;
2082
2083 d += sprintf(d, "%s", args[1]);
2084 for(i=2; *args[i]; i++)
2085 d += sprintf(d, " %s", args[i]);
2086
2087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2089 curproxy->state = PR_STSTOPPED;
2090 }
2091 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2092 curproxy->state = PR_STNEW;
2093 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002094 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2095 int cur_arg = 1;
2096 unsigned int set = 0;
2097
2098 while (*args[cur_arg]) {
2099 int u;
2100 if (strcmp(args[cur_arg], "all") == 0) {
2101 set = 0;
2102 break;
2103 }
2104 else if (strcmp(args[cur_arg], "odd") == 0) {
2105 set |= 0x55555555;
2106 }
2107 else if (strcmp(args[cur_arg], "even") == 0) {
2108 set |= 0xAAAAAAAA;
2109 }
2110 else {
2111 u = str2uic(args[cur_arg]);
2112 if (u < 1 || u > 32) {
2113 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2114 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002117 }
2118 if (u > global.nbproc) {
2119 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002122 }
2123 set |= 1 << (u - 1);
2124 }
2125 cur_arg++;
2126 }
2127 curproxy->bind_proc = set;
2128 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002129 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002130 if (curproxy == &defproxy) {
2131 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002134 }
2135
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002136 err = invalid_char(args[1]);
2137 if (err) {
2138 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2139 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002140 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002141 }
2142
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002143 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2144 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2145 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002148 }
2149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2151 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 if (*(args[1]) == 0) {
2157 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002162
Willy Tarreau67402132012-05-31 20:40:20 +02002163 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002164 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002165 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002166 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 curproxy->cookie_name = strdup(args[1]);
2168 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002169
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 cur_arg = 2;
2171 while (*(args[cur_arg])) {
2172 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002173 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 }
2175 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002176 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 }
2178 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002179 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 }
2181 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002182 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }
2184 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002185 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002187 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002188 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002191 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002193 else if (!strcmp(args[cur_arg], "httponly")) {
2194 curproxy->ck_opts |= PR_CK_HTTPONLY;
2195 }
2196 else if (!strcmp(args[cur_arg], "secure")) {
2197 curproxy->ck_opts |= PR_CK_SECURE;
2198 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002199 else if (!strcmp(args[cur_arg], "domain")) {
2200 if (!*args[cur_arg + 1]) {
2201 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2202 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002203 err_code |= ERR_ALERT | ERR_FATAL;
2204 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002205 }
2206
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002207 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002208 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002209 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2210 " dots nor does not start with a dot."
2211 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002212 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002213 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002214 }
2215
2216 err = invalid_domainchar(args[cur_arg + 1]);
2217 if (err) {
2218 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2219 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002222 }
2223
Willy Tarreau68a897b2009-12-03 23:28:34 +01002224 if (!curproxy->cookie_domain) {
2225 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2226 } else {
2227 /* one domain was already specified, add another one by
2228 * building the string which will be returned along with
2229 * the cookie.
2230 */
2231 char *new_ptr;
2232 int new_len = strlen(curproxy->cookie_domain) +
2233 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2234 new_ptr = malloc(new_len);
2235 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2236 free(curproxy->cookie_domain);
2237 curproxy->cookie_domain = new_ptr;
2238 }
Willy Tarreau31936852010-10-06 16:59:56 +02002239 cur_arg++;
2240 }
2241 else if (!strcmp(args[cur_arg], "maxidle")) {
2242 unsigned int maxidle;
2243 const char *res;
2244
2245 if (!*args[cur_arg + 1]) {
2246 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2247 file, linenum, args[cur_arg]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
2252 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2253 if (res) {
2254 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2255 file, linenum, *res, args[cur_arg]);
2256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
2258 }
2259 curproxy->cookie_maxidle = maxidle;
2260 cur_arg++;
2261 }
2262 else if (!strcmp(args[cur_arg], "maxlife")) {
2263 unsigned int maxlife;
2264 const char *res;
2265
2266 if (!*args[cur_arg + 1]) {
2267 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2268 file, linenum, args[cur_arg]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272
2273 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2274 if (res) {
2275 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2276 file, linenum, *res, args[cur_arg]);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002281 cur_arg++;
2282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002284 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 +02002285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 }
2289 cur_arg++;
2290 }
Willy Tarreau67402132012-05-31 20:40:20 +02002291 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2293 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 }
2296
Willy Tarreau67402132012-05-31 20:40:20 +02002297 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2299 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002302
Willy Tarreau67402132012-05-31 20:40:20 +02002303 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002304 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2305 file, linenum);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002309 else if (!strcmp(args[0], "persist")) { /* persist */
2310 if (*(args[1]) == 0) {
2311 Alert("parsing [%s:%d] : missing persist method.\n",
2312 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002315 }
2316
2317 if (!strncmp(args[1], "rdp-cookie", 10)) {
2318 curproxy->options2 |= PR_O2_RDPC_PRST;
2319
Emeric Brunb982a3d2010-01-04 15:45:53 +01002320 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002321 const char *beg, *end;
2322
2323 beg = args[1] + 11;
2324 end = strchr(beg, ')');
2325
2326 if (!end || end == beg) {
2327 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2328 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002331 }
2332
2333 free(curproxy->rdp_cookie_name);
2334 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2335 curproxy->rdp_cookie_len = end-beg;
2336 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002337 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002338 free(curproxy->rdp_cookie_name);
2339 curproxy->rdp_cookie_name = strdup("msts");
2340 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2341 }
2342 else { /* syntax */
2343 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2344 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002347 }
2348 }
2349 else {
2350 Alert("parsing [%s:%d] : unknown persist method.\n",
2351 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002352 err_code |= ERR_ALERT | ERR_FATAL;
2353 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002354 }
2355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002357 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002359 if (curproxy == &defproxy) {
2360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364
Willy Tarreau977b8e42006-12-29 14:19:17 +01002365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002367
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002369 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002375 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 curproxy->appsession_name = strdup(args[1]);
2377 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2378 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002379 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2380 if (err) {
2381 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2382 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002385 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002386 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002387
Willy Tarreau51041c72007-09-09 21:56:53 +02002388 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2389 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_ABORT;
2391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002393
2394 cur_arg = 6;
2395 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002396 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2397 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002398 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002399 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002400 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002401 } else if (!strcmp(args[cur_arg], "prefix")) {
2402 curproxy->options2 |= PR_O2_AS_PFX;
2403 } else if (!strcmp(args[cur_arg], "mode")) {
2404 if (!*args[cur_arg + 1]) {
2405 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2406 file, linenum, args[0], args[cur_arg]);
2407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
2409 }
2410
2411 cur_arg++;
2412 if (!strcmp(args[cur_arg], "query-string")) {
2413 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2414 curproxy->options2 |= PR_O2_AS_M_QS;
2415 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2416 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2417 curproxy->options2 |= PR_O2_AS_M_PP;
2418 } else {
2419 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
2422 }
2423 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002424 cur_arg++;
2425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 } /* Url App Session */
2427 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002428 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002432 if (curproxy == &defproxy) {
2433 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
2436 }
2437
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (*(args[4]) == 0) {
2439 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2440 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002444 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 curproxy->capture_name = strdup(args[2]);
2446 curproxy->capture_namelen = strlen(curproxy->capture_name);
2447 curproxy->capture_len = atol(args[4]);
2448 if (curproxy->capture_len >= CAPTURE_LEN) {
2449 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2450 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 curproxy->capture_len = CAPTURE_LEN - 1;
2453 }
2454 curproxy->to_log |= LW_COOKIE;
2455 }
2456 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2457 struct cap_hdr *hdr;
2458
2459 if (curproxy == &defproxy) {
2460 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 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 }
2464
2465 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2466 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2467 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 }
2471
2472 hdr = calloc(sizeof(struct cap_hdr), 1);
2473 hdr->next = curproxy->req_cap;
2474 hdr->name = strdup(args[3]);
2475 hdr->namelen = strlen(args[3]);
2476 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002477 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 hdr->index = curproxy->nb_req_cap++;
2479 curproxy->req_cap = hdr;
2480 curproxy->to_log |= LW_REQHDR;
2481 }
2482 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2483 struct cap_hdr *hdr;
2484
2485 if (curproxy == &defproxy) {
2486 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 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }
2490
2491 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2492 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2493 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
2497 hdr = calloc(sizeof(struct cap_hdr), 1);
2498 hdr->next = curproxy->rsp_cap;
2499 hdr->name = strdup(args[3]);
2500 hdr->namelen = strlen(args[3]);
2501 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002502 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 hdr->index = curproxy->nb_rsp_cap++;
2504 curproxy->rsp_cap = hdr;
2505 curproxy->to_log |= LW_RSPHDR;
2506 }
2507 else {
2508 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2509 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002512 }
2513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002515 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002517
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 if (*(args[1]) == 0) {
2519 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524 curproxy->conn_retries = atol(args[1]);
2525 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002526 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002527 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002528
2529 if (curproxy == &defproxy) {
2530 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534
Willy Tarreauff011f22011-01-06 17:51:27 +01002535 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 +01002536 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2537 file, linenum, args[0]);
2538 err_code |= ERR_WARN;
2539 }
2540
Willy Tarreauff011f22011-01-06 17:51:27 +01002541 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002542
Willy Tarreauff011f22011-01-06 17:51:27 +01002543 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002544 err_code |= ERR_ALERT | ERR_ABORT;
2545 goto out;
2546 }
2547
Willy Tarreauff011f22011-01-06 17:51:27 +01002548 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2549 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002550 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002551 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2552 /* set the header name and length into the proxy structure */
2553 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2554 err_code |= ERR_WARN;
2555
2556 if (!*args[1]) {
2557 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2558 file, linenum, args[0]);
2559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
2561 }
2562
2563 /* set the desired header name */
2564 free(curproxy->server_id_hdr_name);
2565 curproxy->server_id_hdr_name = strdup(args[1]);
2566 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2567 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002568 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002569 if (curproxy == &defproxy) {
2570 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002573 }
2574
Willy Tarreauef6494c2010-01-28 17:12:36 +01002575 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002576 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2577 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002580 }
2581
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002582 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2583 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2584 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002587 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002588
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002589 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002590 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002591 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002592 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 struct redirect_rule *rule;
2594 int cur_arg;
2595 int type = REDIRECT_TYPE_NONE;
2596 int code = 302;
2597 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002598 char *cookie = NULL;
2599 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002600 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601
Cyril Bonté99ed3272010-01-24 23:29:44 +01002602 if (curproxy == &defproxy) {
2603 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
2606 }
2607
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 cur_arg = 1;
2609 while (*(args[cur_arg])) {
2610 if (!strcmp(args[cur_arg], "location")) {
2611 if (!*args[cur_arg + 1]) {
2612 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2613 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002616 }
2617
2618 type = REDIRECT_TYPE_LOCATION;
2619 cur_arg++;
2620 destination = args[cur_arg];
2621 }
2622 else if (!strcmp(args[cur_arg], "prefix")) {
2623 if (!*args[cur_arg + 1]) {
2624 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2625 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 }
2629
2630 type = REDIRECT_TYPE_PREFIX;
2631 cur_arg++;
2632 destination = args[cur_arg];
2633 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002634 else if (!strcmp(args[cur_arg], "set-cookie")) {
2635 if (!*args[cur_arg + 1]) {
2636 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2637 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 }
2641
2642 cur_arg++;
2643 cookie = args[cur_arg];
2644 cookie_set = 1;
2645 }
2646 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2647 if (!*args[cur_arg + 1]) {
2648 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002652 }
2653
2654 cur_arg++;
2655 cookie = args[cur_arg];
2656 cookie_set = 0;
2657 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002658 else if (!strcmp(args[cur_arg],"code")) {
2659 if (!*args[cur_arg + 1]) {
2660 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2661 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 }
2665 cur_arg++;
2666 code = atol(args[cur_arg]);
2667 if (code < 301 || code > 303) {
2668 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2669 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 }
2673 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002674 else if (!strcmp(args[cur_arg],"drop-query")) {
2675 flags |= REDIRECT_FLAG_DROP_QS;
2676 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002677 else if (!strcmp(args[cur_arg],"append-slash")) {
2678 flags |= REDIRECT_FLAG_APPEND_SLASH;
2679 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 else if (strcmp(args[cur_arg], "if") == 0 ||
2681 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002682 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002683 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002684 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2685 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002689 break;
2690 }
2691 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002692 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 +02002693 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002696 }
2697 cur_arg++;
2698 }
2699
2700 if (type == REDIRECT_TYPE_NONE) {
2701 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002705 }
2706
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002707 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2708 rule->cond = cond;
2709 rule->rdr_str = strdup(destination);
2710 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002711 if (cookie) {
2712 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002713 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002714 */
2715 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002716 if (cookie_set) {
2717 rule->cookie_str = malloc(rule->cookie_len + 10);
2718 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2719 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2720 rule->cookie_len += 9;
2721 } else {
2722 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002723 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002724 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2725 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002726 }
2727 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002728 rule->type = type;
2729 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002730 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002731 LIST_INIT(&rule->list);
2732 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002733 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2734 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002735 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002736 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002737 struct switching_rule *rule;
2738
Willy Tarreaub099aca2008-10-12 17:26:37 +02002739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 }
2744
Willy Tarreau55ea7572007-06-17 19:56:27 +02002745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002746 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002747
2748 if (*(args[1]) == 0) {
2749 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002752 }
2753
Willy Tarreauef6494c2010-01-28 17:12:36 +01002754 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002755 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2756 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002759 }
2760
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002761 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2762 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2763 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002766 }
2767
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002768 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002769
Willy Tarreau55ea7572007-06-17 19:56:27 +02002770 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2771 rule->cond = cond;
2772 rule->be.name = strdup(args[1]);
2773 LIST_INIT(&rule->list);
2774 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2775 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002776 else if (strcmp(args[0], "use-server") == 0) {
2777 struct server_rule *rule;
2778
2779 if (curproxy == &defproxy) {
2780 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
2785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2786 err_code |= ERR_WARN;
2787
2788 if (*(args[1]) == 0) {
2789 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793
2794 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2795 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2796 file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2802 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2803 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807
2808 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2809
2810 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2811 rule->cond = cond;
2812 rule->srv.name = strdup(args[1]);
2813 LIST_INIT(&rule->list);
2814 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2815 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2816 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002817 else if ((!strcmp(args[0], "force-persist")) ||
2818 (!strcmp(args[0], "ignore-persist"))) {
2819 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002820
2821 if (curproxy == &defproxy) {
2822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825 }
2826
2827 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2828 err_code |= ERR_WARN;
2829
Willy Tarreauef6494c2010-01-28 17:12:36 +01002830 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002831 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2832 file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002837 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2838 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2839 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002844 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002845
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002846 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002847 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002848 if (!strcmp(args[0], "force-persist")) {
2849 rule->type = PERSIST_TYPE_FORCE;
2850 } else {
2851 rule->type = PERSIST_TYPE_IGNORE;
2852 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002853 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002854 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002855 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002856 else if (!strcmp(args[0], "stick-table")) {
2857 int myidx = 1;
2858
Emeric Brun32da3c42010-09-23 18:39:19 +02002859 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002860 curproxy->table.type = (unsigned int)-1;
2861 while (*args[myidx]) {
2862 const char *err;
2863
2864 if (strcmp(args[myidx], "size") == 0) {
2865 myidx++;
2866 if (!*(args[myidx])) {
2867 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2868 file, linenum, args[myidx-1]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2873 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2874 file, linenum, *err, args[myidx-1]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002880 else if (strcmp(args[myidx], "peers") == 0) {
2881 myidx++;
2882 if (!*(args[myidx])) {
2883 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2884 file, linenum, args[myidx-1]);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888 curproxy->table.peers.name = strdup(args[myidx++]);
2889 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 else if (strcmp(args[myidx], "expire") == 0) {
2891 myidx++;
2892 if (!*(args[myidx])) {
2893 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2894 file, linenum, args[myidx-1]);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
2897 }
2898 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2899 if (err) {
2900 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2901 file, linenum, *err, args[myidx-1]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002906 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002907 }
2908 else if (strcmp(args[myidx], "nopurge") == 0) {
2909 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002910 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 }
2912 else if (strcmp(args[myidx], "type") == 0) {
2913 myidx++;
2914 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2915 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2916 file, linenum, args[myidx]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002920 /* myidx already points to next arg */
2921 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002922 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002923 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002924 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002925
2926 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002927 nw = args[myidx];
2928 while (*nw) {
2929 /* the "store" keyword supports a comma-separated list */
2930 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002931 sa = NULL; /* store arg */
2932 while (*nw && *nw != ',') {
2933 if (*nw == '(') {
2934 *nw = 0;
2935 sa = ++nw;
2936 while (*nw != ')') {
2937 if (!*nw) {
2938 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2939 file, linenum, args[0], cw);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943 nw++;
2944 }
2945 *nw = '\0';
2946 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002947 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002948 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002949 if (*nw)
2950 *nw++ = '\0';
2951 type = stktable_get_data_type(cw);
2952 if (type < 0) {
2953 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2954 file, linenum, args[0], cw);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
2957 }
Willy Tarreauac782882010-06-20 10:41:54 +02002958
2959 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2960 switch (err) {
2961 case PE_NONE: break;
2962 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002963 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2964 file, linenum, args[0], cw);
2965 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002966 break;
2967
2968 case PE_ARG_MISSING:
2969 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2970 file, linenum, args[0], cw);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973
2974 case PE_ARG_NOT_USED:
2975 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2976 file, linenum, args[0], cw);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979
2980 default:
2981 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2982 file, linenum, args[0], cw);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002985 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002986 }
2987 myidx++;
2988 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002989 else {
2990 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2991 file, linenum, args[myidx]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002994 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002995 }
2996
2997 if (!curproxy->table.size) {
2998 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2999 file, linenum);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
3003
3004 if (curproxy->table.type == (unsigned int)-1) {
3005 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3006 file, linenum);
3007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
3009 }
3010 }
3011 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003012 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003013 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003014 int myidx = 0;
3015 const char *name = NULL;
3016 int flags;
3017
3018 if (curproxy == &defproxy) {
3019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
3024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3025 err_code |= ERR_WARN;
3026 goto out;
3027 }
3028
3029 myidx++;
3030 if ((strcmp(args[myidx], "store") == 0) ||
3031 (strcmp(args[myidx], "store-request") == 0)) {
3032 myidx++;
3033 flags = STK_IS_STORE;
3034 }
3035 else if (strcmp(args[myidx], "store-response") == 0) {
3036 myidx++;
3037 flags = STK_IS_STORE | STK_ON_RSP;
3038 }
3039 else if (strcmp(args[myidx], "match") == 0) {
3040 myidx++;
3041 flags = STK_IS_MATCH;
3042 }
3043 else if (strcmp(args[myidx], "on") == 0) {
3044 myidx++;
3045 flags = STK_IS_MATCH | STK_IS_STORE;
3046 }
3047 else {
3048 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052
3053 if (*(args[myidx]) == 0) {
3054 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058
David du Colombier7af46052012-05-16 14:16:48 +02003059 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003061 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065
3066 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003067 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3069 file, linenum, args[0], expr->fetch->kw);
3070 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003071 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003072 goto out;
3073 }
3074 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003075 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003076 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3077 file, linenum, args[0], expr->fetch->kw);
3078 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003079 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003080 goto out;
3081 }
3082 }
3083
3084 if (strcmp(args[myidx], "table") == 0) {
3085 myidx++;
3086 name = args[myidx++];
3087 }
3088
Willy Tarreauef6494c2010-01-28 17:12:36 +01003089 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003090 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3091 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3092 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003093 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003094 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003095 goto out;
3096 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003097 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003098 else if (*(args[myidx])) {
3099 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3100 file, linenum, args[0], args[myidx]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003102 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003103 goto out;
3104 }
Emeric Brun97679e72010-09-23 17:56:44 +02003105 if (flags & STK_ON_RSP)
3106 err_code |= warnif_cond_requires_req(cond, file, linenum);
3107 else
3108 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003109
Emeric Brunb982a3d2010-01-04 15:45:53 +01003110 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3111 rule->cond = cond;
3112 rule->expr = expr;
3113 rule->flags = flags;
3114 rule->table.name = name ? strdup(name) : NULL;
3115 LIST_INIT(&rule->list);
3116 if (flags & STK_ON_RSP)
3117 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3118 else
3119 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003122 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003124
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3126 curproxy->uri_auth = NULL; /* we must detach from the default config */
3127
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003128 if (!*args[1]) {
3129 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003130 } else if (!strcmp(args[1], "admin")) {
3131 struct stats_admin_rule *rule;
3132
3133 if (curproxy == &defproxy) {
3134 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
3139 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3140 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
3143 }
3144
3145 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3146 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3147 file, linenum, args[0], args[1]);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003151 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3152 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3153 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
3158 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3159
3160 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3161 rule->cond = cond;
3162 LIST_INIT(&rule->list);
3163 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 } else if (!strcmp(args[1], "uri")) {
3165 if (*(args[2]) == 0) {
3166 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3170 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_ABORT;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174 } else if (!strcmp(args[1], "realm")) {
3175 if (*(args[2]) == 0) {
3176 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3180 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003181 err_code |= ERR_ALERT | ERR_ABORT;
3182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003184 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003185 unsigned interval;
3186
3187 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3188 if (err) {
3189 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3190 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003193 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003197 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003198 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003199 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003200
3201 if (curproxy == &defproxy) {
3202 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3208 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
3211 }
3212
Willy Tarreauff011f22011-01-06 17:51:27 +01003213 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3214 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003215 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3216 file, linenum, args[0]);
3217 err_code |= ERR_WARN;
3218 }
3219
Willy Tarreauff011f22011-01-06 17:51:27 +01003220 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003221
Willy Tarreauff011f22011-01-06 17:51:27 +01003222 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003223 err_code |= ERR_ALERT | ERR_ABORT;
3224 goto out;
3225 }
3226
Willy Tarreauff011f22011-01-06 17:51:27 +01003227 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3228 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 } else if (!strcmp(args[1], "auth")) {
3231 if (*(args[2]) == 0) {
3232 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3236 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003237 err_code |= ERR_ALERT | ERR_ABORT;
3238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 }
3240 } else if (!strcmp(args[1], "scope")) {
3241 if (*(args[2]) == 0) {
3242 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3246 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_ABORT;
3248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 }
3250 } else if (!strcmp(args[1], "enable")) {
3251 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3252 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003253 err_code |= ERR_ALERT | ERR_ABORT;
3254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003256 } else if (!strcmp(args[1], "hide-version")) {
3257 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3258 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_ABORT;
3260 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003261 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003262 } else if (!strcmp(args[1], "show-legends")) {
3263 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003268 } else if (!strcmp(args[1], "show-node")) {
3269
3270 if (*args[2]) {
3271 int i;
3272 char c;
3273
3274 for (i=0; args[2][i]; i++) {
3275 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003276 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3277 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003278 break;
3279 }
3280
3281 if (!i || args[2][i]) {
3282 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3283 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3284 file, linenum, args[0], args[1]);
3285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
3287 }
3288 }
3289
3290 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
3295 } else if (!strcmp(args[1], "show-desc")) {
3296 char *desc = NULL;
3297
3298 if (*args[2]) {
3299 int i, len=0;
3300 char *d;
3301
3302 for(i=2; *args[i]; i++)
3303 len += strlen(args[i])+1;
3304
3305 desc = d = (char *)calloc(1, len);
3306
3307 d += sprintf(d, "%s", args[2]);
3308 for(i=3; *args[i]; i++)
3309 d += sprintf(d, " %s", args[i]);
3310 }
3311
3312 if (!*args[2] && !global.desc)
3313 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3314 file, linenum, args[1]);
3315 else {
3316 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3317 free(desc);
3318 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3319 err_code |= ERR_ALERT | ERR_ABORT;
3320 goto out;
3321 }
3322 free(desc);
3323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003325stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003326 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 +01003327 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 }
3331 }
3332 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003333 int optnum;
3334
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003335 if (*(args[1]) == '\0') {
3336 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003341
3342 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3343 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003344 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3345 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3346 file, linenum, cfg_opts[optnum].name);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
Willy Tarreau93893792009-07-23 13:19:11 +02003350 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3351 err_code |= ERR_WARN;
3352 goto out;
3353 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003354
Willy Tarreau3842f002009-06-14 11:39:52 +02003355 curproxy->no_options &= ~cfg_opts[optnum].val;
3356 curproxy->options &= ~cfg_opts[optnum].val;
3357
3358 switch (kwm) {
3359 case KWM_STD:
3360 curproxy->options |= cfg_opts[optnum].val;
3361 break;
3362 case KWM_NO:
3363 curproxy->no_options |= cfg_opts[optnum].val;
3364 break;
3365 case KWM_DEF: /* already cleared */
3366 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003367 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003368
Willy Tarreau93893792009-07-23 13:19:11 +02003369 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003370 }
3371 }
3372
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003373 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3374 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003375 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3376 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3377 file, linenum, cfg_opts2[optnum].name);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
Willy Tarreau93893792009-07-23 13:19:11 +02003381 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3382 err_code |= ERR_WARN;
3383 goto out;
3384 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003385
Willy Tarreau3842f002009-06-14 11:39:52 +02003386 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3387 curproxy->options2 &= ~cfg_opts2[optnum].val;
3388
3389 switch (kwm) {
3390 case KWM_STD:
3391 curproxy->options2 |= cfg_opts2[optnum].val;
3392 break;
3393 case KWM_NO:
3394 curproxy->no_options2 |= cfg_opts2[optnum].val;
3395 break;
3396 case KWM_DEF: /* already cleared */
3397 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003398 }
Willy Tarreau93893792009-07-23 13:19:11 +02003399 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003400 }
3401 }
3402
Willy Tarreau3842f002009-06-14 11:39:52 +02003403 if (kwm != KWM_STD) {
3404 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003405 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003408 }
3409
Emeric Brun3a058f32009-06-30 18:26:00 +02003410 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003411 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003413 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003414 if (*(args[2]) != '\0') {
3415 if (!strcmp(args[2], "clf")) {
3416 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003417 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003418 } else {
3419 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003422 }
3423 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003424 if (curproxy->logformat_string != default_http_log_format &&
3425 curproxy->logformat_string != default_tcp_log_format &&
3426 curproxy->logformat_string != clf_http_log_format)
3427 free(curproxy->logformat_string);
3428 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003429 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003430 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003432 if (curproxy->logformat_string != default_http_log_format &&
3433 curproxy->logformat_string != default_tcp_log_format &&
3434 curproxy->logformat_string != clf_http_log_format)
3435 free(curproxy->logformat_string);
3436 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 else if (!strcmp(args[1], "tcpka")) {
3439 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003440 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003441 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003442
3443 if (curproxy->cap & PR_CAP_FE)
3444 curproxy->options |= PR_O_TCP_CLI_KA;
3445 if (curproxy->cap & PR_CAP_BE)
3446 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
3448 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003450 err_code |= ERR_WARN;
3451
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003453 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003455 curproxy->options2 &= ~PR_O2_CHK_ANY;
3456 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 if (!*args[2]) { /* no argument */
3458 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3459 curproxy->check_len = strlen(DEF_CHECK_REQ);
3460 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003461 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 curproxy->check_req = (char *)malloc(reqlen);
3463 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003464 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003466 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 if (*args[4])
3468 reqlen += strlen(args[4]);
3469 else
3470 reqlen += strlen("HTTP/1.0");
3471
3472 curproxy->check_req = (char *)malloc(reqlen);
3473 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003474 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003476 }
3477 else if (!strcmp(args[1], "ssl-hello-chk")) {
3478 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003479 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003480 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003481
Willy Tarreaua534fea2008-08-03 12:19:50 +02003482 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003483 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003484 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003485 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
Willy Tarreau23677902007-05-08 23:50:35 +02003487 else if (!strcmp(args[1], "smtpchk")) {
3488 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003489 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003490 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003491 curproxy->options2 &= ~PR_O2_CHK_ANY;
3492 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003493
3494 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3495 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3496 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3497 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3498 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3499 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3500 curproxy->check_req = (char *)malloc(reqlen);
3501 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3502 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3503 } else {
3504 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3505 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3506 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3507 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3508 }
3509 }
3510 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003511 else if (!strcmp(args[1], "pgsql-check")) {
3512 /* use PostgreSQL request to check servers' health */
3513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3514 err_code |= ERR_WARN;
3515
3516 free(curproxy->check_req);
3517 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003518 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003519 curproxy->options2 |= PR_O2_PGSQL_CHK;
3520
3521 if (*(args[2])) {
3522 int cur_arg = 2;
3523
3524 while (*(args[cur_arg])) {
3525 if (strcmp(args[cur_arg], "user") == 0) {
3526 char * packet;
3527 uint32_t packet_len;
3528 uint32_t pv;
3529
3530 /* suboption header - needs additional argument for it */
3531 if (*(args[cur_arg+1]) == 0) {
3532 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3533 file, linenum, args[0], args[1], args[cur_arg]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537
3538 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3539 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3540 pv = htonl(0x30000); /* protocol version 3.0 */
3541
3542 packet = (char*) calloc(1, packet_len);
3543
3544 memcpy(packet + 4, &pv, 4);
3545
3546 /* copy "user" */
3547 memcpy(packet + 8, "user", 4);
3548
3549 /* copy username */
3550 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3551
3552 free(curproxy->check_req);
3553 curproxy->check_req = packet;
3554 curproxy->check_len = packet_len;
3555
3556 packet_len = htonl(packet_len);
3557 memcpy(packet, &packet_len, 4);
3558 cur_arg += 2;
3559 } else {
3560 /* unknown suboption - catchall */
3561 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3562 file, linenum, args[0], args[1]);
3563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
3565 }
3566 } /* end while loop */
3567 }
3568 }
3569
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003570 else if (!strcmp(args[1], "redis-check")) {
3571 /* use REDIS PING request to check servers' health */
3572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3573 err_code |= ERR_WARN;
3574
3575 free(curproxy->check_req);
3576 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003577 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003578 curproxy->options2 |= PR_O2_REDIS_CHK;
3579
3580 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3581 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3582 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3583 }
3584
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003585 else if (!strcmp(args[1], "mysql-check")) {
3586 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003587 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3588 err_code |= ERR_WARN;
3589
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003590 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003591 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003592 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003593 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003594
3595 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3596 * const char mysql40_client_auth_pkt[] = {
3597 * "\x0e\x00\x00" // packet length
3598 * "\x01" // packet number
3599 * "\x00\x00" // client capabilities
3600 * "\x00\x00\x01" // max packet
3601 * "haproxy\x00" // username (null terminated string)
3602 * "\x00" // filler (always 0x00)
3603 * "\x01\x00\x00" // packet length
3604 * "\x00" // packet number
3605 * "\x01" // COM_QUIT command
3606 * };
3607 */
3608
3609 if (*(args[2])) {
3610 int cur_arg = 2;
3611
3612 while (*(args[cur_arg])) {
3613 if (strcmp(args[cur_arg], "user") == 0) {
3614 char *mysqluser;
3615 int packetlen, reqlen, userlen;
3616
3617 /* suboption header - needs additional argument for it */
3618 if (*(args[cur_arg+1]) == 0) {
3619 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3620 file, linenum, args[0], args[1], args[cur_arg]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 mysqluser = args[cur_arg + 1];
3625 userlen = strlen(mysqluser);
3626 packetlen = userlen + 7;
3627 reqlen = packetlen + 9;
3628
3629 free(curproxy->check_req);
3630 curproxy->check_req = (char *)calloc(1, reqlen);
3631 curproxy->check_len = reqlen;
3632
3633 snprintf(curproxy->check_req, 4, "%c%c%c",
3634 ((unsigned char) packetlen & 0xff),
3635 ((unsigned char) (packetlen >> 8) & 0xff),
3636 ((unsigned char) (packetlen >> 16) & 0xff));
3637
3638 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003639 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003640 curproxy->check_req[8] = 1;
3641 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3642 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3643 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
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 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003654 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003655 else if (!strcmp(args[1], "ldap-check")) {
3656 /* use LDAP request to check servers' health */
3657 free(curproxy->check_req);
3658 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003659 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003660 curproxy->options2 |= PR_O2_LDAP_CHK;
3661
3662 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3663 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3664 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3665 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003666 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003667 int cur_arg;
3668
3669 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3670 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003671 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003672
Willy Tarreau87cf5142011-08-19 22:57:24 +02003673 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003674
3675 free(curproxy->fwdfor_hdr_name);
3676 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3677 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3678
3679 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3680 cur_arg = 2;
3681 while (*(args[cur_arg])) {
3682 if (!strcmp(args[cur_arg], "except")) {
3683 /* suboption except - needs additional argument for it */
3684 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3685 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3686 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_ALERT | ERR_FATAL;
3688 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003689 }
3690 /* flush useless bits */
3691 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003692 cur_arg += 2;
3693 } else if (!strcmp(args[cur_arg], "header")) {
3694 /* suboption header - needs additional argument for it */
3695 if (*(args[cur_arg+1]) == 0) {
3696 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3697 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003698 err_code |= ERR_ALERT | ERR_FATAL;
3699 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003700 }
3701 free(curproxy->fwdfor_hdr_name);
3702 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3703 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3704 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003705 } else if (!strcmp(args[cur_arg], "if-none")) {
3706 curproxy->options &= ~PR_O_FF_ALWAYS;
3707 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003708 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003709 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003710 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003711 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003714 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003715 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003716 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003717 else if (!strcmp(args[1], "originalto")) {
3718 int cur_arg;
3719
3720 /* insert x-original-to field, but not for the IP address listed as an except.
3721 * set default options (ie: bitfield, header name, etc)
3722 */
3723
3724 curproxy->options |= PR_O_ORGTO;
3725
3726 free(curproxy->orgto_hdr_name);
3727 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3728 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3729
Willy Tarreau87cf5142011-08-19 22:57:24 +02003730 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003731 cur_arg = 2;
3732 while (*(args[cur_arg])) {
3733 if (!strcmp(args[cur_arg], "except")) {
3734 /* suboption except - needs additional argument for it */
3735 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3736 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3737 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003740 }
3741 /* flush useless bits */
3742 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3743 cur_arg += 2;
3744 } else if (!strcmp(args[cur_arg], "header")) {
3745 /* suboption header - needs additional argument for it */
3746 if (*(args[cur_arg+1]) == 0) {
3747 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3748 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003751 }
3752 free(curproxy->orgto_hdr_name);
3753 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3754 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3755 cur_arg += 2;
3756 } else {
3757 /* unknown suboption - catchall */
3758 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3759 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003762 }
3763 } /* end while loop */
3764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 else {
3766 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
Willy Tarreau93893792009-07-23 13:19:11 +02003770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003772 else if (!strcmp(args[0], "default_backend")) {
3773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003775
3776 if (*(args[1]) == 0) {
3777 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003780 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003781 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003782 curproxy->defbe.name = strdup(args[1]);
3783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003787
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003788 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 /* enable reconnections to dispatch */
3792 curproxy->options |= PR_O_REDISP;
3793 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003794 else if (!strcmp(args[0], "http-check")) {
3795 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003797
3798 if (strcmp(args[1], "disable-on-404") == 0) {
3799 /* enable a graceful server shutdown on an HTTP 404 response */
3800 curproxy->options |= PR_O_DISABLE404;
3801 }
Willy Tarreauef781042010-01-27 11:53:01 +01003802 else if (strcmp(args[1], "send-state") == 0) {
3803 /* enable emission of the apparent state of a server in HTTP checks */
3804 curproxy->options2 |= PR_O2_CHK_SNDST;
3805 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003806 else if (strcmp(args[1], "expect") == 0) {
3807 const char *ptr_arg;
3808 int cur_arg;
3809
3810 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3811 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815
3816 cur_arg = 2;
3817 /* consider exclamation marks, sole or at the beginning of a word */
3818 while (*(ptr_arg = args[cur_arg])) {
3819 while (*ptr_arg == '!') {
3820 curproxy->options2 ^= PR_O2_EXP_INV;
3821 ptr_arg++;
3822 }
3823 if (*ptr_arg)
3824 break;
3825 cur_arg++;
3826 }
3827 /* now ptr_arg points to the beginning of a word past any possible
3828 * exclamation mark, and cur_arg is the argument which holds this word.
3829 */
3830 if (strcmp(ptr_arg, "status") == 0) {
3831 if (!*(args[cur_arg + 1])) {
3832 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3833 file, linenum, args[0], args[1], ptr_arg);
3834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
3836 }
3837 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003838 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003839 curproxy->expect_str = strdup(args[cur_arg + 1]);
3840 }
3841 else if (strcmp(ptr_arg, "string") == 0) {
3842 if (!*(args[cur_arg + 1])) {
3843 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3844 file, linenum, args[0], args[1], ptr_arg);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003849 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003850 curproxy->expect_str = strdup(args[cur_arg + 1]);
3851 }
3852 else if (strcmp(ptr_arg, "rstatus") == 0) {
3853 if (!*(args[cur_arg + 1])) {
3854 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3855 file, linenum, args[0], args[1], ptr_arg);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003860 free(curproxy->expect_str);
3861 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3862 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003863 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3864 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3865 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3866 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870 }
3871 else if (strcmp(ptr_arg, "rstring") == 0) {
3872 if (!*(args[cur_arg + 1])) {
3873 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3874 file, linenum, args[0], args[1], ptr_arg);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003879 free(curproxy->expect_str);
3880 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3881 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003882 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3883 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3884 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3885 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 }
3890 else {
3891 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3892 file, linenum, args[0], args[1], ptr_arg);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003897 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003898 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 +02003899 err_code |= ERR_ALERT | ERR_FATAL;
3900 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003901 }
3902 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003903 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003904 if (curproxy == &defproxy) {
3905 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003908 }
3909
Willy Tarreaub80c2302007-11-30 20:51:32 +01003910 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003912
3913 if (strcmp(args[1], "fail") == 0) {
3914 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003915 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003916 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3917 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003918 err_code |= ERR_ALERT | ERR_FATAL;
3919 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003920 }
3921
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003922 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3923 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3924 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003925 err_code |= ERR_ALERT | ERR_FATAL;
3926 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003927 }
3928 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3929 }
3930 else {
3931 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003934 }
3935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936#ifdef TPROXY
3937 else if (!strcmp(args[0], "transparent")) {
3938 /* enable transparent proxy connections */
3939 curproxy->options |= PR_O_TRANSP;
3940 }
3941#endif
3942 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003945
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 if (*(args[1]) == 0) {
3947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
3951 curproxy->maxconn = atol(args[1]);
3952 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003953 else if (!strcmp(args[0], "backlog")) { /* backlog */
3954 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003955 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003956
3957 if (*(args[1]) == 0) {
3958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003961 }
3962 curproxy->backlog = atol(args[1]);
3963 }
Willy Tarreau86034312006-12-29 00:10:33 +01003964 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003967
Willy Tarreau86034312006-12-29 00:10:33 +01003968 if (*(args[1]) == 0) {
3969 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003972 }
3973 curproxy->fullconn = atol(args[1]);
3974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003975 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3976 if (*(args[1]) == 0) {
3977 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003981 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3982 if (err) {
3983 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3984 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003987 }
3988 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 }
3990 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003991 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 if (curproxy == &defproxy) {
3993 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003997 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003999
Willy Tarreaubaaee002006-06-26 02:48:02 +02004000 if (strchr(args[1], ':') == NULL) {
4001 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004005 sk = str2sa(args[1]);
4006 if (!sk) {
4007 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004012 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
4014 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004015 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004016 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004018 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4019 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004024 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4026 err_code |= ERR_WARN;
4027
4028 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4029 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4030 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4031 }
4032 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4033 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4034 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4035 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004036 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4037 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4038 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4039 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004040 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004041 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004046 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 char *rport, *raddr;
4049 short realport = 0;
4050 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004057 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004058 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059
4060 if (!*args[2]) {
4061 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4062 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004066
4067 err = invalid_char(args[1]);
4068 if (err) {
4069 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4070 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004073 }
4074
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004075 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004076 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004077
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004078 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4079 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4080 err_code |= ERR_ALERT | ERR_ABORT;
4081 goto out;
4082 }
4083
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004084 /* the servers are linked backwards first */
4085 newsrv->next = curproxy->srv;
4086 curproxy->srv = newsrv;
4087 newsrv->proxy = curproxy;
4088 newsrv->conf.file = file;
4089 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090
Simon Hormanaf514952011-06-21 14:34:57 +09004091 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004092 LIST_INIT(&newsrv->pendconns);
4093 do_check = 0;
4094 newsrv->state = SRV_RUNNING; /* early server setup */
4095 newsrv->last_change = now.tv_sec;
4096 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004099 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 * - IP: => port=+0, relative
4101 * - IP:N => port=N, absolute
4102 * - IP:+N => port=+N, relative
4103 * - IP:-N => port=-N, relative
4104 */
4105 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004106 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004107 if (rport) {
4108 *rport++ = 0;
4109 realport = atol(rport);
4110 if (!isdigit((unsigned char)*rport))
4111 newsrv->state |= SRV_MAPPORTS;
4112 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114
Willy Tarreaufab5a432011-03-04 15:31:53 +01004115 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004117 if (!sk) {
4118 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
4122 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004123 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004124 newsrv->data = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004125
4126 if (!sk) {
4127 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4128 file, linenum, newsrv->addr.ss_family, args[2]);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004132 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004133
4134 newsrv->check_port = curproxy->defsrv.check_port;
4135 newsrv->inter = curproxy->defsrv.inter;
4136 newsrv->fastinter = curproxy->defsrv.fastinter;
4137 newsrv->downinter = curproxy->defsrv.downinter;
4138 newsrv->rise = curproxy->defsrv.rise;
4139 newsrv->fall = curproxy->defsrv.fall;
4140 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4141 newsrv->minconn = curproxy->defsrv.minconn;
4142 newsrv->maxconn = curproxy->defsrv.maxconn;
4143 newsrv->slowstart = curproxy->defsrv.slowstart;
4144 newsrv->onerror = curproxy->defsrv.onerror;
4145 newsrv->consecutive_errors_limit
4146 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004147#ifdef OPENSSL
4148 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4149#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 newsrv->uweight = newsrv->iweight
4151 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 newsrv->curfd = -1; /* no health-check in progress */
4154 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004156 cur_arg = 3;
4157 } else {
4158 newsrv = &curproxy->defsrv;
4159 cur_arg = 1;
4160 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004161
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004163 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004164 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004165
4166 if (!*args[cur_arg + 1]) {
4167 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4168 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004171 }
4172
4173 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004174 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004175
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004176 if (newsrv->puid <= 0) {
4177 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004178 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004181 }
4182
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004183 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4184 if (node) {
4185 struct server *target = container_of(node, struct server, conf.id);
4186 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4187 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
4190 }
4191 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004192 cur_arg += 2;
4193 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004194 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 newsrv->cookie = strdup(args[cur_arg + 1]);
4196 newsrv->cklen = strlen(args[cur_arg + 1]);
4197 cur_arg += 2;
4198 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004199 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004200 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4201 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4202 cur_arg += 2;
4203 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004205 if (!*args[cur_arg + 1]) {
4206 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4207 file, linenum, args[cur_arg]);
4208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004213 if (newsrv->rise <= 0) {
4214 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4215 file, linenum, args[cur_arg]);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 }
4219
Willy Tarreau96839092010-03-29 10:02:24 +02004220 if (newsrv->health)
4221 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004222 cur_arg += 2;
4223 }
4224 else if (!strcmp(args[cur_arg], "fall")) {
4225 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004226
4227 if (!*args[cur_arg + 1]) {
4228 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4229 file, linenum, args[cur_arg]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
4234 if (newsrv->fall <= 0) {
4235 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4236 file, linenum, args[cur_arg]);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239 }
4240
Willy Tarreaubaaee002006-06-26 02:48:02 +02004241 cur_arg += 2;
4242 }
4243 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004244 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4245 if (err) {
4246 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4247 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004250 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004251 if (val <= 0) {
4252 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4253 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004256 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004257 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 cur_arg += 2;
4259 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004260 else if (!strcmp(args[cur_arg], "fastinter")) {
4261 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4262 if (err) {
4263 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4264 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004267 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004268 if (val <= 0) {
4269 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4270 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004273 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004274 newsrv->fastinter = val;
4275 cur_arg += 2;
4276 }
4277 else if (!strcmp(args[cur_arg], "downinter")) {
4278 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4279 if (err) {
4280 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4281 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004284 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004285 if (val <= 0) {
4286 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4287 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004290 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004291 newsrv->downinter = val;
4292 cur_arg += 2;
4293 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004294 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004295 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004296 if (!sk) {
4297 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
4301 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004302 cur_arg += 2;
4303 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 else if (!strcmp(args[cur_arg], "port")) {
4305 newsrv->check_port = atol(args[cur_arg + 1]);
4306 cur_arg += 2;
4307 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004308 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 newsrv->state |= SRV_BACKUP;
4310 cur_arg ++;
4311 }
Simon Hormanfa461682011-06-25 09:39:49 +09004312 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4313 newsrv->state |= SRV_NON_STICK;
4314 cur_arg ++;
4315 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004316 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4317 newsrv->state |= SRV_SEND_PROXY;
4318 cur_arg ++;
4319 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 else if (!strcmp(args[cur_arg], "weight")) {
4321 int w;
4322 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004323 if (w < 0 || w > 256) {
4324 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004329 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004330 cur_arg += 2;
4331 }
4332 else if (!strcmp(args[cur_arg], "minconn")) {
4333 newsrv->minconn = atol(args[cur_arg + 1]);
4334 cur_arg += 2;
4335 }
4336 else if (!strcmp(args[cur_arg], "maxconn")) {
4337 newsrv->maxconn = atol(args[cur_arg + 1]);
4338 cur_arg += 2;
4339 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004340 else if (!strcmp(args[cur_arg], "maxqueue")) {
4341 newsrv->maxqueue = atol(args[cur_arg + 1]);
4342 cur_arg += 2;
4343 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004344 else if (!strcmp(args[cur_arg], "slowstart")) {
4345 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004346 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004347 if (err) {
4348 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4349 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004352 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004353 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004354 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4355 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004358 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004359 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004360 cur_arg += 2;
4361 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004362 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004363
4364 if (!*args[cur_arg + 1]) {
4365 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4366 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004369 }
4370
4371 newsrv->trackit = strdup(args[cur_arg + 1]);
4372
4373 cur_arg += 2;
4374 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004375 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004376 global.maxsock++;
4377 do_check = 1;
4378 cur_arg += 1;
4379 }
Willy Tarreau96839092010-03-29 10:02:24 +02004380 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4381 newsrv->state |= SRV_MAINTAIN;
4382 newsrv->state &= ~SRV_RUNNING;
4383 newsrv->health = 0;
4384 cur_arg += 1;
4385 }
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004386 else if (!strcmp(args[cur_arg], "ssl")) {
4387#ifdef USE_OPENSSL
4388 newsrv->use_ssl = 1;
4389 cur_arg += 1;
4390#else /* USE_OPENSSL */
4391 Alert("parsing [%s:%d]: '%s' option not implemented.\n",
4392 file, linenum, args[cur_arg]);
4393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
4395#endif /* USE_OPENSSL */
4396 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004397 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004398 if (!strcmp(args[cur_arg + 1], "none"))
4399 newsrv->observe = HANA_OBS_NONE;
4400 else if (!strcmp(args[cur_arg + 1], "layer4"))
4401 newsrv->observe = HANA_OBS_LAYER4;
4402 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4403 if (curproxy->mode != PR_MODE_HTTP) {
4404 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4405 file, linenum, args[cur_arg + 1]);
4406 err_code |= ERR_ALERT;
4407 }
4408 newsrv->observe = HANA_OBS_LAYER7;
4409 }
4410 else {
4411 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004412 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004413 file, linenum, args[cur_arg], args[cur_arg + 1]);
4414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
4416 }
4417
4418 cur_arg += 2;
4419 }
4420 else if (!strcmp(args[cur_arg], "on-error")) {
4421 if (!strcmp(args[cur_arg + 1], "fastinter"))
4422 newsrv->onerror = HANA_ONERR_FASTINTER;
4423 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4424 newsrv->onerror = HANA_ONERR_FAILCHK;
4425 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4426 newsrv->onerror = HANA_ONERR_SUDDTH;
4427 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4428 newsrv->onerror = HANA_ONERR_MARKDWN;
4429 else {
4430 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004431 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004432 file, linenum, args[cur_arg], args[cur_arg + 1]);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 }
4436
4437 cur_arg += 2;
4438 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004439 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4440 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4441 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4442 else {
4443 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4444 file, linenum, args[cur_arg], args[cur_arg + 1]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
4448
4449 cur_arg += 2;
4450 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004451 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4452 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4453 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4454 else {
4455 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4456 file, linenum, args[cur_arg], args[cur_arg + 1]);
4457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
4459 }
4460
4461 cur_arg += 2;
4462 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004463 else if (!strcmp(args[cur_arg], "error-limit")) {
4464 if (!*args[cur_arg + 1]) {
4465 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4466 file, linenum, args[cur_arg]);
4467 err_code |= ERR_ALERT | ERR_FATAL;
4468 goto out;
4469 }
4470
4471 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4472
4473 if (newsrv->consecutive_errors_limit <= 0) {
4474 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4475 file, linenum, args[cur_arg]);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004479 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004480 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004481 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004482 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004483 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004484
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004486#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004488 file, linenum, "source", "usesrc");
4489#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004490 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004492#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 }
4496 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004497 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4498 if (!sk) {
4499 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
4502 }
4503 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004504
4505 if (port_low != port_high) {
4506 int i;
4507 if (port_low <= 0 || port_low > 65535 ||
4508 port_high <= 0 || port_high > 65535 ||
4509 port_low > port_high) {
4510 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4511 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004514 }
4515 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4516 for (i = 0; i < newsrv->sport_range->size; i++)
4517 newsrv->sport_range->ports[i] = port_low + i;
4518 }
4519
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004521 while (*(args[cur_arg])) {
4522 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004523#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4524#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004525 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4526 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4527 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004530 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004531#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004532 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004533 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004534 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004537 }
4538 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004539 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004540 newsrv->state |= SRV_TPROXY_CLI;
4541 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004542 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004543 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004544 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4545 char *name, *end;
4546
4547 name = args[cur_arg+1] + 7;
4548 while (isspace(*name))
4549 name++;
4550
4551 end = name;
4552 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4553 end++;
4554
4555 newsrv->state &= ~SRV_TPROXY_MASK;
4556 newsrv->state |= SRV_TPROXY_DYN;
4557 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4558 newsrv->bind_hdr_len = end - name;
4559 memcpy(newsrv->bind_hdr_name, name, end - name);
4560 newsrv->bind_hdr_name[end-name] = '\0';
4561 newsrv->bind_hdr_occ = -1;
4562
4563 /* now look for an occurrence number */
4564 while (isspace(*end))
4565 end++;
4566 if (*end == ',') {
4567 end++;
4568 name = end;
4569 if (*end == '-')
4570 end++;
4571 while (isdigit(*end))
4572 end++;
4573 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4574 }
4575
4576 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4577 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4578 " occurrences values smaller than %d.\n",
4579 file, linenum, MAX_HDR_HISTORY);
4580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
4582 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004583 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004584 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004585 if (!sk) {
4586 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
4589 }
4590 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004591 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004592 }
4593 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004594#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004595 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004596#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004597 cur_arg += 2;
4598 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004599#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004600 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004601 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004604#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4605 } /* "usesrc" */
4606
4607 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4608#ifdef SO_BINDTODEVICE
4609 if (!*args[cur_arg + 1]) {
4610 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004614 }
4615 if (newsrv->iface_name)
4616 free(newsrv->iface_name);
4617
4618 newsrv->iface_name = strdup(args[cur_arg + 1]);
4619 newsrv->iface_len = strlen(newsrv->iface_name);
4620 global.last_checks |= LSTCHK_NETADM;
4621#else
4622 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4623 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004626#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004627 cur_arg += 2;
4628 continue;
4629 }
4630 /* this keyword in not an option of "source" */
4631 break;
4632 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004634 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004635 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4636 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004639 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004641 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004642 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 +01004643 file, linenum, newsrv->id);
4644 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004645 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 +01004646 file, linenum);
4647
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 }
4651 }
4652
4653 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004654 if (newsrv->trackit) {
4655 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4656 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004659 }
4660
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004661 /* try to get the port from check_addr if check_port not set */
4662 if (!newsrv->check_port)
4663 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004664
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4666 newsrv->check_port = realport; /* by default */
4667 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004668 /* not yet valid, because no port was set on
4669 * the server either. We'll check if we have
4670 * a known port on the first listener.
4671 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004672 struct listener *l = curproxy->listen;
4673 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4674 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004675 }
4676 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4678 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004679 err_code |= ERR_ALERT | ERR_FATAL;
4680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004682
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004683 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004684 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004685 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4686 err_code |= ERR_ALERT | ERR_ABORT;
4687 goto out;
4688 }
4689
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004690 /* Allocate buffer for partial check results... */
4691 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4692 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4693 err_code |= ERR_ALERT | ERR_ABORT;
4694 goto out;
4695 }
4696
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004697 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004698 newsrv->state |= SRV_CHECKED;
4699 }
4700
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004701 if (!defsrv) {
4702 if (newsrv->state & SRV_BACKUP)
4703 curproxy->srv_bck++;
4704 else
4705 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004706
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004707 newsrv->prev_state = newsrv->state;
4708 }
William Lallemanda73203e2012-03-12 12:48:57 +01004709 }
4710
4711 else if (strcmp(args[0], "unique-id-format") == 0) {
4712 if (!*(args[1])) {
4713 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004717 free(curproxy->uniqueid_format_string);
4718 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004719 }
William Lallemanda73203e2012-03-12 12:48:57 +01004720
4721 else if (strcmp(args[0], "unique-id-header") == 0) {
4722 if (!*(args[1])) {
4723 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
4727 free(curproxy->header_unique_id);
4728 curproxy->header_unique_id = strdup(args[1]);
4729 }
4730
William Lallemand723b73a2012-02-08 16:37:49 +01004731 else if (strcmp(args[0], "log-format") == 0) {
4732 if (!*(args[1])) {
4733 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
4736 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004737
4738 if (curproxy->logformat_string != default_http_log_format &&
4739 curproxy->logformat_string != default_tcp_log_format &&
4740 curproxy->logformat_string != clf_http_log_format)
4741 free(curproxy->logformat_string);
4742 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
William Lallemand723b73a2012-02-08 16:37:49 +01004744
William Lallemand0f99e342011-10-12 17:50:54 +02004745 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4746 /* delete previous herited or defined syslog servers */
4747 struct logsrv *back;
4748
4749 if (*(args[1]) != 0) {
4750 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
4753 }
4754
William Lallemand723b73a2012-02-08 16:37:49 +01004755 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4756 LIST_DEL(&tmplogsrv->list);
4757 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004758 }
4759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004761 struct logsrv *logsrv;
4762
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004764 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004765 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004766 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004767 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004768 LIST_INIT(&node->list);
4769 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004773
4774 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775
William Lallemand0f99e342011-10-12 17:50:54 +02004776 logsrv->facility = get_log_facility(args[2]);
4777 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 }
4783
William Lallemand0f99e342011-10-12 17:50:54 +02004784 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004786 logsrv->level = get_log_level(args[3]);
4787 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004788 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
4793 }
4794
William Lallemand0f99e342011-10-12 17:50:54 +02004795 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004796 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004797 logsrv->minlvl = get_log_level(args[4]);
4798 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004799 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004803 }
4804 }
4805
Robert Tsai81ae1952007-12-05 10:47:29 +01004806 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004807 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004808 if (!sk) {
4809 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004810 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
William Lallemand0f99e342011-10-12 17:50:54 +02004814 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004815 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004816 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004817 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004818 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
William Lallemand0f99e342011-10-12 17:50:54 +02004822 logsrv->addr = *sk;
4823 if (!get_host_port(&logsrv->addr))
4824 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004825 }
William Lallemand0f99e342011-10-12 17:50:54 +02004826
4827 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else {
4830 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4831 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
4835 }
4836 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004837 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004838 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004839
Willy Tarreau977b8e42006-12-29 14:19:17 +01004840 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004841 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004842
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004844 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4845 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004849
4850 /* we must first clear any optional default setting */
4851 curproxy->options &= ~PR_O_TPXY_MASK;
4852 free(curproxy->iface_name);
4853 curproxy->iface_name = NULL;
4854 curproxy->iface_len = 0;
4855
Willy Tarreaud5191e72010-02-09 20:50:45 +01004856 sk = str2sa(args[1]);
4857 if (!sk) {
4858 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
4862 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004864
4865 cur_arg = 2;
4866 while (*(args[cur_arg])) {
4867 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004868#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4869#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004870 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4871 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4872 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004875 }
4876#endif
4877 if (!*args[cur_arg + 1]) {
4878 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4879 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004882 }
4883
4884 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004885 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004886 curproxy->options |= PR_O_TPXY_CLI;
4887 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004888 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004889 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004890 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4891 char *name, *end;
4892
4893 name = args[cur_arg+1] + 7;
4894 while (isspace(*name))
4895 name++;
4896
4897 end = name;
4898 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4899 end++;
4900
4901 curproxy->options &= ~PR_O_TPXY_MASK;
4902 curproxy->options |= PR_O_TPXY_DYN;
4903 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4904 curproxy->bind_hdr_len = end - name;
4905 memcpy(curproxy->bind_hdr_name, name, end - name);
4906 curproxy->bind_hdr_name[end-name] = '\0';
4907 curproxy->bind_hdr_occ = -1;
4908
4909 /* now look for an occurrence number */
4910 while (isspace(*end))
4911 end++;
4912 if (*end == ',') {
4913 end++;
4914 name = end;
4915 if (*end == '-')
4916 end++;
4917 while (isdigit(*end))
4918 end++;
4919 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4920 }
4921
4922 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4923 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4924 " occurrences values smaller than %d.\n",
4925 file, linenum, MAX_HDR_HISTORY);
4926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
4928 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004929 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004930 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004931 if (!sk) {
4932 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935 }
4936 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004937 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004938 }
4939 global.last_checks |= LSTCHK_NETADM;
4940#if !defined(CONFIG_HAP_LINUX_TPROXY)
4941 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004942#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004943#else /* no TPROXY support */
4944 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004945 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004948#endif
4949 cur_arg += 2;
4950 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004951 }
4952
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004953 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4954#ifdef SO_BINDTODEVICE
4955 if (!*args[cur_arg + 1]) {
4956 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4957 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004960 }
4961 if (curproxy->iface_name)
4962 free(curproxy->iface_name);
4963
4964 curproxy->iface_name = strdup(args[cur_arg + 1]);
4965 curproxy->iface_len = strlen(curproxy->iface_name);
4966 global.last_checks |= LSTCHK_NETADM;
4967#else
4968 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4969 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004972#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004973 cur_arg += 2;
4974 continue;
4975 }
4976 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4977 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004982 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4983 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4984 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004985 err_code |= ERR_ALERT | ERR_FATAL;
4986 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004989 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4991 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995
4996 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004997 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004998 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005004 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005005 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005011 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005012 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
5016 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005018 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005019 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005022 }
5023 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005024 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005025 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005026 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005030 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005031 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005032 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005033 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005035 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005036 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005037 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005039 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005040 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005041 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005042 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005043 }
5044 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005046 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005047 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005049 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005058
5059 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005060 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005061 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005062 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005067 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005068 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005069 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 }
5072 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005074 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005075 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005076 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005078 }
5079 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005081 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005082 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005083 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005085 }
5086 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005087 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005088 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005089 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005090 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005093 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005094 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005095 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005096 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005098 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005099 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005101 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005102
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 if (curproxy == &defproxy) {
5104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005108 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 if (*(args[1]) == 0) {
5112 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005116
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005117 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005118 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5119 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5120 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
5124 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5125 }
5126 else if (*args[2]) {
5127 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5128 file, linenum, args[0], args[2]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005133 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005134 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005135 wl->s = strdup(args[1]);
5136 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005137 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005138 }
5139 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005146
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005149 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
5153 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005155 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005156 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005157 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
5160 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005163 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5170 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005177 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005184 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
5188 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005191 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 }
5195 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005196 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005197
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 if (curproxy == &defproxy) {
5199 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005203 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205
Willy Tarreaubaaee002006-06-26 02:48:02 +02005206 if (*(args[1]) == 0) {
5207 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 }
5211
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005212 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005213 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5214 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5215 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219 err_code |= warnif_cond_requires_req(cond, file, linenum);
5220 }
5221 else if (*args[2]) {
5222 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5223 file, linenum, args[0], args[2]);
5224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
5226 }
5227
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005228 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005229 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005230 wl->s = strdup(args[1]);
5231 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 }
5233 else if (!strcmp(args[0], "errorloc") ||
5234 !strcmp(args[0], "errorloc302") ||
5235 !strcmp(args[0], "errorloc303")) { /* error location */
5236 int errnum, errlen;
5237 char *err;
5238
Willy Tarreau977b8e42006-12-29 14:19:17 +01005239 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005241
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005243 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
5247
5248 errnum = atol(args[1]);
5249 if (!strcmp(args[0], "errorloc303")) {
5250 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5251 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5252 } else {
5253 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5254 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5255 }
5256
Willy Tarreau0f772532006-12-23 20:51:41 +01005257 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5258 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005259 chunk_destroy(&curproxy->errmsg[rc]);
5260 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005261 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005264
5265 if (rc >= HTTP_ERR_SIZE) {
5266 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5267 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 free(err);
5269 }
5270 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005271 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5272 int errnum, errlen, fd;
5273 char *err;
5274 struct stat stat;
5275
5276 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005277 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005278
5279 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005280 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005283 }
5284
5285 fd = open(args[2], O_RDONLY);
5286 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5287 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5288 file, linenum, args[2], args[1]);
5289 if (fd >= 0)
5290 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005293 }
5294
Willy Tarreau27a674e2009-08-17 07:23:33 +02005295 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005296 errlen = stat.st_size;
5297 } else {
5298 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005299 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005300 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005301 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005302 }
5303
5304 err = malloc(errlen); /* malloc() must succeed during parsing */
5305 errnum = read(fd, err, errlen);
5306 if (errnum != errlen) {
5307 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5308 file, linenum, args[2], args[1]);
5309 close(fd);
5310 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_ALERT | ERR_FATAL;
5312 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005313 }
5314 close(fd);
5315
5316 errnum = atol(args[1]);
5317 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5318 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005319 chunk_destroy(&curproxy->errmsg[rc]);
5320 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005321 break;
5322 }
5323 }
5324
5325 if (rc >= HTTP_ERR_SIZE) {
5326 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5327 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005328 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005329 free(err);
5330 }
5331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005333 struct cfg_kw_list *kwl;
5334 int index;
5335
5336 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5337 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5338 if (kwl->kw[index].section != CFG_LISTEN)
5339 continue;
5340 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5341 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005342 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005343 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005344 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005345 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005346 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005347 err_code |= ERR_ALERT | ERR_FATAL;
5348 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005349 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005350 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005351 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005352 err_code |= ERR_WARN;
5353 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005354 }
Willy Tarreau93893792009-07-23 13:19:11 +02005355 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005356 }
5357 }
5358 }
5359
Willy Tarreau6daf3432008-01-22 16:44:08 +01005360 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
Willy Tarreau93893792009-07-23 13:19:11 +02005364 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005365 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005366 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367}
5368
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005369int
5370cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5371{
5372
5373 int err_code = 0;
5374 const char *err;
5375
5376 if (!strcmp(args[0], "userlist")) { /* new userlist */
5377 struct userlist *newul;
5378
5379 if (!*args[1]) {
5380 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5381 file, linenum, args[0]);
5382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
5385
5386 err = invalid_char(args[1]);
5387 if (err) {
5388 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5389 file, linenum, *err, args[0], args[1]);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393
5394 for (newul = userlist; newul; newul = newul->next)
5395 if (!strcmp(newul->name, args[1])) {
5396 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5397 file, linenum, args[1]);
5398 err_code |= ERR_WARN;
5399 goto out;
5400 }
5401
5402 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5403 if (!newul) {
5404 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5405 err_code |= ERR_ALERT | ERR_ABORT;
5406 goto out;
5407 }
5408
5409 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5410 newul->name = strdup(args[1]);
5411
5412 if (!newul->groupusers | !newul->name) {
5413 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5414 err_code |= ERR_ALERT | ERR_ABORT;
5415 goto out;
5416 }
5417
5418 newul->next = userlist;
5419 userlist = newul;
5420
5421 } else if (!strcmp(args[0], "group")) { /* new group */
5422 int cur_arg, i;
5423 const char *err;
5424
5425 if (!*args[1]) {
5426 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5427 file, linenum, args[0]);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431
5432 err = invalid_char(args[1]);
5433 if (err) {
5434 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5435 file, linenum, *err, args[0], args[1]);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439
5440 for(i = 0; i < userlist->grpcnt; i++)
5441 if (!strcmp(userlist->groups[i], args[1])) {
5442 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5443 file, linenum, args[1], userlist->name);
5444 err_code |= ERR_ALERT;
5445 goto out;
5446 }
5447
5448 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5449 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5450 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454
5455 cur_arg = 2;
5456
5457 while (*args[cur_arg]) {
5458 if (!strcmp(args[cur_arg], "users")) {
5459 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5460 cur_arg += 2;
5461 continue;
5462 } else {
5463 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5464 file, linenum, args[0]);
5465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
5467 }
5468 }
5469
5470 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5471 } else if (!strcmp(args[0], "user")) { /* new user */
5472 struct auth_users *newuser;
5473 int cur_arg;
5474
5475 if (!*args[1]) {
5476 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5477 file, linenum, args[0]);
5478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
5480 }
5481
5482 for (newuser = userlist->users; newuser; newuser = newuser->next)
5483 if (!strcmp(newuser->user, args[1])) {
5484 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5485 file, linenum, args[1], userlist->name);
5486 err_code |= ERR_ALERT;
5487 goto out;
5488 }
5489
5490 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5491 if (!newuser) {
5492 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5493 err_code |= ERR_ALERT | ERR_ABORT;
5494 goto out;
5495 }
5496
5497 newuser->user = strdup(args[1]);
5498
5499 newuser->next = userlist->users;
5500 userlist->users = newuser;
5501
5502 cur_arg = 2;
5503
5504 while (*args[cur_arg]) {
5505 if (!strcmp(args[cur_arg], "password")) {
5506#ifndef CONFIG_HAP_CRYPT
5507 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5508 file, linenum);
5509 err_code |= ERR_ALERT;
5510#endif
5511 newuser->pass = strdup(args[cur_arg + 1]);
5512 cur_arg += 2;
5513 continue;
5514 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5515 newuser->pass = strdup(args[cur_arg + 1]);
5516 newuser->flags |= AU_O_INSECURE;
5517 cur_arg += 2;
5518 continue;
5519 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005520 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005521 cur_arg += 2;
5522 continue;
5523 } else {
5524 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5525 file, linenum, args[0]);
5526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
5528 }
5529 }
5530 } else {
5531 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5532 err_code |= ERR_ALERT | ERR_FATAL;
5533 }
5534
5535out:
5536 return err_code;
5537}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538
5539/*
5540 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005541 * Returns the error code, 0 if OK, or any combination of :
5542 * - ERR_ABORT: must abort ASAP
5543 * - ERR_FATAL: we can continue parsing but not start the service
5544 * - ERR_WARN: a warning has been emitted
5545 * - ERR_ALERT: an alert has been emitted
5546 * Only the two first ones can stop processing, the two others are just
5547 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005549int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005551 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 FILE *f;
5553 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005555 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 if ((f=fopen(file,"r")) == NULL)
5558 return -1;
5559
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005560 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005561 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005562 char *end;
5563 char *args[MAX_LINE_ARGS + 1];
5564 char *line = thisline;
5565
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 linenum++;
5567
5568 end = line + strlen(line);
5569
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005570 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5571 /* Check if we reached the limit and the last char is not \n.
5572 * Watch out for the last line without the terminating '\n'!
5573 */
5574 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005575 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005576 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005577 }
5578
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005580 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 line++;
5582
5583 arg = 0;
5584 args[arg] = line;
5585
5586 while (*line && arg < MAX_LINE_ARGS) {
5587 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5588 * C equivalent value. Other combinations left unchanged (eg: \1).
5589 */
5590 if (*line == '\\') {
5591 int skip = 0;
5592 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5593 *line = line[1];
5594 skip = 1;
5595 }
5596 else if (line[1] == 'r') {
5597 *line = '\r';
5598 skip = 1;
5599 }
5600 else if (line[1] == 'n') {
5601 *line = '\n';
5602 skip = 1;
5603 }
5604 else if (line[1] == 't') {
5605 *line = '\t';
5606 skip = 1;
5607 }
5608 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005609 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 unsigned char hex1, hex2;
5611 hex1 = toupper(line[2]) - '0';
5612 hex2 = toupper(line[3]) - '0';
5613 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5614 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5615 *line = (hex1<<4) + hex2;
5616 skip = 3;
5617 }
5618 else {
5619 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005620 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
5622 }
5623 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005624 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 end -= skip;
5626 }
5627 line++;
5628 }
5629 else if (*line == '#' || *line == '\n' || *line == '\r') {
5630 /* end of string, end of loop */
5631 *line = 0;
5632 break;
5633 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005634 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005636 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005637 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 line++;
5639 args[++arg] = line;
5640 }
5641 else {
5642 line++;
5643 }
5644 }
5645
5646 /* empty line */
5647 if (!**args)
5648 continue;
5649
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005650 if (*line) {
5651 /* we had to stop due to too many args.
5652 * Let's terminate the string, print the offending part then cut the
5653 * last arg.
5654 */
5655 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5656 line++;
5657 *line = '\0';
5658
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005659 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005660 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 args[arg] = line;
5663 }
5664
Willy Tarreau540abe42007-05-02 20:50:16 +02005665 /* zero out remaining args and ensure that at least one entry
5666 * is zeroed out.
5667 */
5668 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 args[arg] = line;
5670 }
5671
Willy Tarreau3842f002009-06-14 11:39:52 +02005672 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005673 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005674 char *tmp;
5675
Willy Tarreau3842f002009-06-14 11:39:52 +02005676 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005677 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005678 for (arg=0; *args[arg+1]; arg++)
5679 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005680 *tmp = '\0'; // fix the next arg to \0
5681 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005682 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005683 else if (!strcmp(args[0], "default")) {
5684 kwm = KWM_DEF;
5685 for (arg=0; *args[arg+1]; arg++)
5686 args[arg] = args[arg+1]; // shift args after inversion
5687 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005688
William Lallemand0f99e342011-10-12 17:50:54 +02005689 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5690 strcmp(args[0], "log") != 0) {
5691 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005692 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005693 }
5694
Willy Tarreau977b8e42006-12-29 14:19:17 +01005695 if (!strcmp(args[0], "listen") ||
5696 !strcmp(args[0], "frontend") ||
5697 !strcmp(args[0], "backend") ||
5698 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005699 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005701 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005702 cursection = strdup(args[0]);
5703 }
5704 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005706 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005707 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005708 }
5709 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005710 confsect = CFG_USERLIST;
5711 free(cursection);
5712 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005713 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005714 else if (!strcmp(args[0], "peers")) {
5715 confsect = CFG_PEERS;
5716 free(cursection);
5717 cursection = strdup(args[0]);
5718 }
5719
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 /* else it's a section keyword */
5721
5722 switch (confsect) {
5723 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 break;
5726 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005727 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005729 case CFG_USERLIST:
5730 err_code |= cfg_parse_users(file, linenum, args, kwm);
5731 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005732 case CFG_PEERS:
5733 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5734 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005736 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005739
5740 if (err_code & ERR_ABORT)
5741 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005743 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005744 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005746 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005747}
5748
Willy Tarreaubb925012009-07-23 13:36:36 +02005749/*
5750 * Returns the error code, 0 if OK, or any combination of :
5751 * - ERR_ABORT: must abort ASAP
5752 * - ERR_FATAL: we can continue parsing but not start the service
5753 * - ERR_WARN: a warning has been emitted
5754 * - ERR_ALERT: an alert has been emitted
5755 * Only the two first ones can stop processing, the two others are just
5756 * indicators.
5757 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005758int check_config_validity()
5759{
5760 int cfgerr = 0;
5761 struct proxy *curproxy = NULL;
5762 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005763 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005764 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005765 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766
5767 /*
5768 * Now, check for the integrity of all that we have collected.
5769 */
5770
5771 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005772 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005773
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005774 /* first, we will invert the proxy list order */
5775 curproxy = NULL;
5776 while (proxy) {
5777 struct proxy *next;
5778
5779 next = proxy->next;
5780 proxy->next = curproxy;
5781 curproxy = proxy;
5782 if (!next)
5783 break;
5784 proxy = next;
5785 }
5786
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005788 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005789 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005790 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005791 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005792 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005793 unsigned int next_id;
5794
5795 if (!curproxy->uuid) {
5796 /* proxy ID not set, use automatic numbering with first
5797 * spare entry starting with next_pxid.
5798 */
5799 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5800 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5801 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005802 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005803 next_pxid++;
5804
Willy Tarreau55ea7572007-06-17 19:56:27 +02005805
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005807 /* ensure we don't keep listeners uselessly bound */
5808 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 curproxy = curproxy->next;
5810 continue;
5811 }
5812
Willy Tarreauff01a212009-03-15 13:46:16 +01005813 switch (curproxy->mode) {
5814 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005815 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005816 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005817 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5818 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005819 cfgerr++;
5820 }
5821
5822 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005823 Warning("config : servers will be ignored for %s '%s'.\n",
5824 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005825 break;
5826
5827 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005828 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005829 break;
5830
5831 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005832 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005833 break;
5834 }
5835
5836 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005837 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5838 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 cfgerr++;
5840 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005841
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005842 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005843 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005844 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005845 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5846 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005847 cfgerr++;
5848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005850 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005851 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5852 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005853 cfgerr++;
5854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005856 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005857 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5858 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005859 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005860 }
5861 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005862 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005863 /* If no LB algo is set in a backend, and we're not in
5864 * transparent mode, dispatch mode nor proxy mode, we
5865 * want to use balance roundrobin by default.
5866 */
5867 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5868 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 }
5870 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005871
Willy Tarreau1620ec32011-08-06 17:05:02 +02005872 if (curproxy->options & PR_O_DISPATCH)
5873 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5874 else if (curproxy->options & PR_O_HTTP_PROXY)
5875 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5876 else if (curproxy->options & PR_O_TRANSP)
5877 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005878
Willy Tarreau1620ec32011-08-06 17:05:02 +02005879 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5880 if (curproxy->options & PR_O_DISABLE404) {
5881 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5882 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5883 err_code |= ERR_WARN;
5884 curproxy->options &= ~PR_O_DISABLE404;
5885 }
5886 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5887 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5888 "send-state", proxy_type_str(curproxy), curproxy->id);
5889 err_code |= ERR_WARN;
5890 curproxy->options &= ~PR_O2_CHK_SNDST;
5891 }
Willy Tarreauef781042010-01-27 11:53:01 +01005892 }
5893
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005894 /* if a default backend was specified, let's find it */
5895 if (curproxy->defbe.name) {
5896 struct proxy *target;
5897
Alex Williams96532db2009-11-01 21:27:13 -05005898 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005899 if (!target) {
5900 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5901 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005902 cfgerr++;
5903 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005904 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5905 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005906 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005907 } else {
5908 free(curproxy->defbe.name);
5909 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005910 /* we force the backend to be present on at least all of
5911 * the frontend's processes.
5912 */
5913 target->bind_proc = curproxy->bind_proc ?
5914 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005915
5916 /* Emit a warning if this proxy also has some servers */
5917 if (curproxy->srv) {
5918 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5919 curproxy->id);
5920 err_code |= ERR_WARN;
5921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 }
5923 }
5924
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005925 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005926 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5927 /* map jump target for ACT_SETBE in req_rep chain */
5928 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005929 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005930 struct proxy *target;
5931
Willy Tarreaua496b602006-12-17 23:15:24 +01005932 if (exp->action != ACT_SETBE)
5933 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005934
Alex Williams96532db2009-11-01 21:27:13 -05005935 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005936 if (!target) {
5937 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5938 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005939 cfgerr++;
5940 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005941 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5942 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005943 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005944 } else {
5945 free((void *)exp->replace);
5946 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005947 /* we force the backend to be present on at least all of
5948 * the frontend's processes.
5949 */
5950 target->bind_proc = curproxy->bind_proc ?
5951 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005952 }
5953 }
5954 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005955
5956 /* find the target proxy for 'use_backend' rules */
5957 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005958 struct proxy *target;
5959
Alex Williams96532db2009-11-01 21:27:13 -05005960 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005961
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005962 if (!target) {
5963 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5964 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005965 cfgerr++;
5966 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005967 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5968 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005969 cfgerr++;
5970 } else {
5971 free((void *)rule->be.name);
5972 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005973 /* we force the backend to be present on at least all of
5974 * the frontend's processes.
5975 */
5976 target->bind_proc = curproxy->bind_proc ?
5977 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005978 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005979 }
5980
5981 /* find the target proxy for 'use_backend' rules */
5982 list_for_each_entry(srule, &curproxy->server_rules, list) {
5983 struct server *target = findserver(curproxy, srule->srv.name);
5984
5985 if (!target) {
5986 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5987 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5988 cfgerr++;
5989 continue;
5990 }
5991 free((void *)srule->srv.name);
5992 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005993 }
5994
Emeric Brunb982a3d2010-01-04 15:45:53 +01005995 /* find the target table for 'stick' rules */
5996 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5997 struct proxy *target;
5998
Emeric Brun1d33b292010-01-04 15:47:17 +01005999 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6000 if (mrule->flags & STK_IS_STORE)
6001 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6002
Emeric Brunb982a3d2010-01-04 15:45:53 +01006003 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006004 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006005 else
6006 target = curproxy;
6007
6008 if (!target) {
6009 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6010 curproxy->id, mrule->table.name);
6011 cfgerr++;
6012 }
6013 else if (target->table.size == 0) {
6014 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6015 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6016 cfgerr++;
6017 }
Willy Tarreau12785782012-04-27 21:37:17 +02006018 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6019 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006020 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6021 cfgerr++;
6022 }
6023 else {
6024 free((void *)mrule->table.name);
6025 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006026 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006027 }
6028 }
6029
6030 /* find the target table for 'store response' rules */
6031 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6032 struct proxy *target;
6033
Emeric Brun1d33b292010-01-04 15:47:17 +01006034 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6035
Emeric Brunb982a3d2010-01-04 15:45:53 +01006036 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006037 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006038 else
6039 target = curproxy;
6040
6041 if (!target) {
6042 Alert("Proxy '%s': unable to find store table '%s'.\n",
6043 curproxy->id, mrule->table.name);
6044 cfgerr++;
6045 }
6046 else if (target->table.size == 0) {
6047 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6048 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6049 cfgerr++;
6050 }
Willy Tarreau12785782012-04-27 21:37:17 +02006051 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6052 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006053 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6054 cfgerr++;
6055 }
6056 else {
6057 free((void *)mrule->table.name);
6058 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006059 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006060 }
6061 }
6062
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006063 /* find the target table for 'tcp-request' layer 4 rules */
6064 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6065 struct proxy *target;
6066
Willy Tarreau56123282010-08-06 19:06:56 +02006067 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006068 continue;
6069
6070 if (trule->act_prm.trk_ctr.table.n)
6071 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6072 else
6073 target = curproxy;
6074
6075 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006076 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6077 curproxy->id, trule->act_prm.trk_ctr.table.n,
6078 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006079 cfgerr++;
6080 }
6081 else if (target->table.size == 0) {
6082 Alert("Proxy '%s': table '%s' used but not configured.\n",
6083 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6084 cfgerr++;
6085 }
6086 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006087 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006088 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6089 cfgerr++;
6090 }
6091 else {
6092 free(trule->act_prm.trk_ctr.table.n);
6093 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006094 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006095 * to pass a list of counters to track and allocate them right here using
6096 * stktable_alloc_data_type().
6097 */
6098 }
6099 }
6100
Willy Tarreaud1f96522010-08-03 19:34:32 +02006101 /* find the target table for 'tcp-request' layer 6 rules */
6102 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6103 struct proxy *target;
6104
Willy Tarreau56123282010-08-06 19:06:56 +02006105 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006106 continue;
6107
6108 if (trule->act_prm.trk_ctr.table.n)
6109 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6110 else
6111 target = curproxy;
6112
6113 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006114 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6115 curproxy->id, trule->act_prm.trk_ctr.table.n,
6116 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006117 cfgerr++;
6118 }
6119 else if (target->table.size == 0) {
6120 Alert("Proxy '%s': table '%s' used but not configured.\n",
6121 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6122 cfgerr++;
6123 }
6124 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006125 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 +02006126 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6127 cfgerr++;
6128 }
6129 else {
6130 free(trule->act_prm.trk_ctr.table.n);
6131 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006132 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006133 * to pass a list of counters to track and allocate them right here using
6134 * stktable_alloc_data_type().
6135 */
6136 }
6137 }
6138
Emeric Brun32da3c42010-09-23 18:39:19 +02006139 if (curproxy->table.peers.name) {
6140 struct peers *curpeers = peers;
6141
6142 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6143 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6144 free((void *)curproxy->table.peers.name);
6145 curproxy->table.peers.p = peers;
6146 break;
6147 }
6148 }
6149
6150 if (!curpeers) {
6151 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6152 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006153 free((void *)curproxy->table.peers.name);
6154 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006155 cfgerr++;
6156 }
6157 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006158 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6159 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006160 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006161 cfgerr++;
6162 }
6163 }
6164
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006165 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006166 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006167 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6168 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6169 "proxy", curproxy->id);
6170 cfgerr++;
6171 goto out_uri_auth_compat;
6172 }
6173
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006174 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006175 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006176 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006177 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006178
Willy Tarreau95fa4692010-02-01 13:05:50 +01006179 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6180 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006181
6182 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006183 uri_auth_compat_req[i++] = "realm";
6184 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6185 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006186
Willy Tarreau95fa4692010-02-01 13:05:50 +01006187 uri_auth_compat_req[i++] = "unless";
6188 uri_auth_compat_req[i++] = "{";
6189 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6190 uri_auth_compat_req[i++] = "}";
6191 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006192
Willy Tarreauff011f22011-01-06 17:51:27 +01006193 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6194 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006195 cfgerr++;
6196 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006197 }
6198
Willy Tarreauff011f22011-01-06 17:51:27 +01006199 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006200
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006201 if (curproxy->uri_auth->auth_realm) {
6202 free(curproxy->uri_auth->auth_realm);
6203 curproxy->uri_auth->auth_realm = NULL;
6204 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006205
6206 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006207 }
6208out_uri_auth_compat:
6209
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006210 cfgerr += acl_find_targets(curproxy);
6211
Willy Tarreau2738a142006-07-08 17:28:09 +02006212 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006213 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006214 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006215 (!curproxy->timeout.connect ||
6216 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006218 " | While not properly invalid, you will certainly encounter various problems\n"
6219 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006220 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006222 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006223 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006224
Willy Tarreau1fa31262007-12-03 00:36:16 +01006225 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6226 * We must still support older configurations, so let's find out whether those
6227 * parameters have been set or must be copied from contimeouts.
6228 */
6229 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006230 if (!curproxy->timeout.tarpit ||
6231 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006232 /* tarpit timeout not set. We search in the following order:
6233 * default.tarpit, curr.connect, default.connect.
6234 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006235 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006236 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006237 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006238 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006239 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006240 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006241 }
6242 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006243 (!curproxy->timeout.queue ||
6244 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006245 /* queue timeout not set. We search in the following order:
6246 * default.queue, curr.connect, default.connect.
6247 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006248 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006249 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006250 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006251 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006252 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006253 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006254 }
6255 }
6256
Willy Tarreau1620ec32011-08-06 17:05:02 +02006257 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006258 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6259 curproxy->check_req = (char *)malloc(curproxy->check_len);
6260 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006261 }
6262
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006263 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006264 if (curproxy->nb_req_cap) {
6265 if (curproxy->mode == PR_MODE_HTTP) {
6266 curproxy->req_cap_pool = create_pool("ptrcap",
6267 curproxy->nb_req_cap * sizeof(char *),
6268 MEM_F_SHARED);
6269 } else {
6270 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6271 proxy_type_str(curproxy), curproxy->id);
6272 err_code |= ERR_WARN;
6273 curproxy->to_log &= ~LW_REQHDR;
6274 curproxy->nb_req_cap = 0;
6275 }
6276 }
6277
6278 if (curproxy->nb_rsp_cap) {
6279 if (curproxy->mode == PR_MODE_HTTP) {
6280 curproxy->rsp_cap_pool = create_pool("ptrcap",
6281 curproxy->nb_rsp_cap * sizeof(char *),
6282 MEM_F_SHARED);
6283 } else {
6284 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6285 proxy_type_str(curproxy), curproxy->id);
6286 err_code |= ERR_WARN;
6287 curproxy->to_log &= ~LW_REQHDR;
6288 curproxy->nb_rsp_cap = 0;
6289 }
6290 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006291
Willy Tarreau196729e2012-05-31 19:30:26 +02006292 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006293 if (!(curproxy->cap & PR_CAP_FE)) {
6294 if (curproxy->logformat_string != default_http_log_format &&
6295 curproxy->logformat_string != default_tcp_log_format &&
6296 curproxy->logformat_string != clf_http_log_format)
6297 free(curproxy->logformat_string);
6298 curproxy->logformat_string = NULL;
6299 }
6300
Willy Tarreau196729e2012-05-31 19:30:26 +02006301 if (curproxy->logformat_string)
6302 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6303
6304 if (curproxy->uniqueid_format_string)
6305 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6306
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 /* first, we will invert the servers list order */
6308 newsrv = NULL;
6309 while (curproxy->srv) {
6310 struct server *next;
6311
6312 next = curproxy->srv->next;
6313 curproxy->srv->next = newsrv;
6314 newsrv = curproxy->srv;
6315 if (!next)
6316 break;
6317 curproxy->srv = next;
6318 }
6319
Willy Tarreaudd701652010-05-25 23:03:02 +02006320 /* assign automatic UIDs to servers which don't have one yet */
6321 next_id = 1;
6322 newsrv = curproxy->srv;
6323 while (newsrv != NULL) {
6324 if (!newsrv->puid) {
6325 /* server ID not set, use automatic numbering with first
6326 * spare entry starting with next_svid.
6327 */
6328 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6329 newsrv->conf.id.key = newsrv->puid = next_id;
6330 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6331 }
6332 next_id++;
6333 newsrv = newsrv->next;
6334 }
6335
Willy Tarreau20697042007-11-15 23:26:18 +01006336 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006337 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006338
Willy Tarreau62c3be22012-01-20 13:12:32 +01006339 /*
6340 * If this server supports a maxconn parameter, it needs a dedicated
6341 * tasks to fill the emptied slots when a connection leaves.
6342 * Also, resolve deferred tracking dependency if needed.
6343 */
6344 newsrv = curproxy->srv;
6345 while (newsrv != NULL) {
6346 if (newsrv->minconn > newsrv->maxconn) {
6347 /* Only 'minconn' was specified, or it was higher than or equal
6348 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6349 * this will avoid further useless expensive computations.
6350 */
6351 newsrv->maxconn = newsrv->minconn;
6352 } else if (newsrv->maxconn && !newsrv->minconn) {
6353 /* minconn was not specified, so we set it to maxconn */
6354 newsrv->minconn = newsrv->maxconn;
6355 }
6356
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006357#ifdef USE_OPENSSL
6358#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6359#define SSL_OP_NO_COMPRESSION 0
6360#endif
6361#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6362#define SSL_MODE_RELEASE_BUFFERS 0
6363#endif
6364#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6365#define SSL_OP_NO_COMPRESSION 0
6366#endif
6367 if (newsrv->use_ssl) {
6368 int ssloptions =
6369 SSL_OP_ALL | /* all known workarounds for bugs */
6370 SSL_OP_NO_SSLv2 |
6371 SSL_OP_NO_COMPRESSION;
6372 int sslmode =
6373 SSL_MODE_ENABLE_PARTIAL_WRITE |
6374 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6375 SSL_MODE_RELEASE_BUFFERS;
6376
6377 /* Initiate SSL context for current server */
6378 newsrv->ssl_ctx.reused_sess = NULL;
6379 newsrv->data = &ssl_sock;
6380 newsrv->ssl_ctx.ctx = SSL_CTX_new(SSLv23_client_method());
6381 if(!newsrv->ssl_ctx.ctx) {
6382
6383 Alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
6384 proxy_type_str(curproxy), curproxy->id,
6385 newsrv->id);
6386 cfgerr++;
6387 goto next_srv;
6388 }
6389
6390 SSL_CTX_set_options(newsrv->ssl_ctx.ctx, ssloptions);
6391 SSL_CTX_set_mode(newsrv->ssl_ctx.ctx, sslmode);
6392 SSL_CTX_set_verify(newsrv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6393 SSL_CTX_set_session_cache_mode(newsrv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
6394 }
6395#endif /* USE_OPENSSL */
Willy Tarreau62c3be22012-01-20 13:12:32 +01006396 if (newsrv->trackit) {
6397 struct proxy *px;
6398 struct server *srv;
6399 char *pname, *sname;
6400
6401 pname = newsrv->trackit;
6402 sname = strrchr(pname, '/');
6403
6404 if (sname)
6405 *sname++ = '\0';
6406 else {
6407 sname = pname;
6408 pname = NULL;
6409 }
6410
6411 if (pname) {
6412 px = findproxy(pname, PR_CAP_BE);
6413 if (!px) {
6414 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6415 proxy_type_str(curproxy), curproxy->id,
6416 newsrv->id, pname);
6417 cfgerr++;
6418 goto next_srv;
6419 }
6420 } else
6421 px = curproxy;
6422
6423 srv = findserver(px, sname);
6424 if (!srv) {
6425 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6426 proxy_type_str(curproxy), curproxy->id,
6427 newsrv->id, sname);
6428 cfgerr++;
6429 goto next_srv;
6430 }
6431
6432 if (!(srv->state & SRV_CHECKED)) {
6433 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6434 "tracking as it does not have checks enabled.\n",
6435 proxy_type_str(curproxy), curproxy->id,
6436 newsrv->id, px->id, srv->id);
6437 cfgerr++;
6438 goto next_srv;
6439 }
6440
6441 if (curproxy != px &&
6442 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6443 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6444 "tracking: disable-on-404 option inconsistency.\n",
6445 proxy_type_str(curproxy), curproxy->id,
6446 newsrv->id, px->id, srv->id);
6447 cfgerr++;
6448 goto next_srv;
6449 }
6450
6451 /* if the other server is forced disabled, we have to do the same here */
6452 if (srv->state & SRV_MAINTAIN) {
6453 newsrv->state |= SRV_MAINTAIN;
6454 newsrv->state &= ~SRV_RUNNING;
6455 newsrv->health = 0;
6456 }
6457
6458 newsrv->track = srv;
6459 newsrv->tracknext = srv->tracknext;
6460 srv->tracknext = newsrv;
6461
6462 free(newsrv->trackit);
6463 newsrv->trackit = NULL;
6464 }
6465 next_srv:
6466 newsrv = newsrv->next;
6467 }
6468
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006469 /* We have to initialize the server lookup mechanism depending
6470 * on what LB algorithm was choosen.
6471 */
6472
6473 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6474 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6475 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006476 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6477 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6478 init_server_map(curproxy);
6479 } else {
6480 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6481 fwrr_init_server_groups(curproxy);
6482 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006483 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006484
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006485 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006486 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6487 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6488 fwlc_init_server_tree(curproxy);
6489 } else {
6490 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6491 fas_init_server_tree(curproxy);
6492 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006493 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006494
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006495 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006496 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6497 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6498 chash_init_server_tree(curproxy);
6499 } else {
6500 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6501 init_server_map(curproxy);
6502 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006503 break;
6504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505
6506 if (curproxy->options & PR_O_LOGASAP)
6507 curproxy->to_log &= ~LW_BYTES;
6508
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006509 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006510 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006511 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6512 proxy_type_str(curproxy), curproxy->id);
6513 err_code |= ERR_WARN;
6514 }
6515
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006516 if (curproxy->mode != PR_MODE_HTTP) {
6517 int optnum;
6518
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006519 if (curproxy->uri_auth) {
6520 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6521 proxy_type_str(curproxy), curproxy->id);
6522 err_code |= ERR_WARN;
6523 curproxy->uri_auth = NULL;
6524 }
6525
Willy Tarreau87cf5142011-08-19 22:57:24 +02006526 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006527 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6528 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6529 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006530 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006531 }
6532
6533 if (curproxy->options & PR_O_ORGTO) {
6534 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6535 "originalto", proxy_type_str(curproxy), curproxy->id);
6536 err_code |= ERR_WARN;
6537 curproxy->options &= ~PR_O_ORGTO;
6538 }
6539
6540 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6541 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6542 (curproxy->cap & cfg_opts[optnum].cap) &&
6543 (curproxy->options & cfg_opts[optnum].val)) {
6544 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6545 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6546 err_code |= ERR_WARN;
6547 curproxy->options &= ~cfg_opts[optnum].val;
6548 }
6549 }
6550
6551 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6552 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6553 (curproxy->cap & cfg_opts2[optnum].cap) &&
6554 (curproxy->options2 & cfg_opts2[optnum].val)) {
6555 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6556 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6557 err_code |= ERR_WARN;
6558 curproxy->options2 &= ~cfg_opts2[optnum].val;
6559 }
6560 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006561
Willy Tarreauefa5f512010-03-30 20:13:29 +02006562#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006563 if (curproxy->bind_hdr_occ) {
6564 curproxy->bind_hdr_occ = 0;
6565 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6566 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6567 err_code |= ERR_WARN;
6568 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006569#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006570 }
6571
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006573 * ensure that we're not cross-dressing a TCP server into HTTP.
6574 */
6575 newsrv = curproxy->srv;
6576 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006577 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006578 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006580 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006581 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006582
Willy Tarreau0cec3312011-10-31 13:49:26 +01006583 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6584 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6585 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6586 err_code |= ERR_WARN;
6587 }
6588
Willy Tarreauefa5f512010-03-30 20:13:29 +02006589#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006590 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6591 newsrv->bind_hdr_occ = 0;
6592 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6593 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6594 err_code |= ERR_WARN;
6595 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006596#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006597 newsrv = newsrv->next;
6598 }
6599
Willy Tarreauc1a21672009-08-16 22:37:44 +02006600 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006601 curproxy->accept = frontend_accept;
6602
Willy Tarreauc1a21672009-08-16 22:37:44 +02006603 if (curproxy->tcp_req.inspect_delay ||
6604 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006605 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006606
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006607 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006608 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006609 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006610 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006611
6612 /* both TCP and HTTP must check switching rules */
6613 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6614 }
6615
6616 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006617 if (curproxy->tcp_req.inspect_delay ||
6618 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6619 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6620
Emeric Brun97679e72010-09-23 17:56:44 +02006621 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6622 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6623
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006624 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006625 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006626 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006627 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006628
6629 /* If the backend does requires RDP cookie persistence, we have to
6630 * enable the corresponding analyser.
6631 */
6632 if (curproxy->options2 & PR_O2_RDPC_PRST)
6633 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6634 }
6635
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006636 listener = NULL;
6637 while (curproxy->listen) {
6638 struct listener *next;
6639
6640 next = curproxy->listen->next;
6641 curproxy->listen->next = listener;
6642 listener = curproxy->listen;
6643
6644 if (!next)
6645 break;
6646
6647 curproxy->listen = next;
6648 }
6649
Willy Tarreaue6b98942007-10-29 01:09:36 +01006650 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006651 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006652 listener = curproxy->listen;
6653 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006654 if (!listener->luid) {
6655 /* listener ID not set, use automatic numbering with first
6656 * spare entry starting with next_luid.
6657 */
6658 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6659 listener->conf.id.key = listener->luid = next_id;
6660 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006661 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006662 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006663
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006664 /* enable separate counters */
6665 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6666 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6667 if (!listener->name) {
6668 sprintf(trash, "sock-%d", listener->luid);
6669 listener->name = strdup(trash);
6670 }
6671 }
6672
Emeric Brun6e159292012-05-18 16:32:13 +02006673#ifdef USE_OPENSSL
6674#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
6675#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
6676#endif
6677#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
6678#define SSL_OP_NO_COMPRESSION 0
6679#endif
6680#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
6681#define SSL_MODE_RELEASE_BUFFERS 0
6682#endif
6683 /* Initialize SSL */
6684 if (listener->ssl_cert) {
6685 int ssloptions =
6686 SSL_OP_ALL | /* all known workarounds for bugs */
6687 SSL_OP_NO_SSLv2 |
6688 SSL_OP_NO_COMPRESSION |
6689 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
6690 int sslmode =
6691 SSL_MODE_ENABLE_PARTIAL_WRITE |
6692 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
6693 SSL_MODE_RELEASE_BUFFERS;
6694
6695 listener->data = &ssl_sock; /* data layer */
6696 listener->ssl_ctx.ctx = SSL_CTX_new(SSLv23_server_method());
6697 if (!listener->ssl_ctx.ctx) {
6698 Alert("Proxy '%s': unable to allocate SSL context to bind listener %d (%s:%d) using cert '%s'.\n",
6699 curproxy->id, listener->luid, listener->conf.file, listener->conf.line, listener->ssl_cert);
6700 cfgerr++;
6701 goto skip_ssl;
6702 }
6703 SSL_CTX_set_options(listener->ssl_ctx.ctx, ssloptions);
6704 SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
6705 SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
6706 SSL_CTX_set_session_cache_mode(listener->ssl_ctx.ctx, SSL_SESS_CACHE_SERVER);
6707
6708 if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
6709 Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
6710 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6711 cfgerr++;
6712 goto skip_ssl;
6713 }
6714
6715 if (SSL_CTX_use_certificate_chain_file(listener->ssl_ctx.ctx, listener->ssl_cert) <= 0) {
6716 Alert("Proxy '%s': unable to load SSL certificate from file '%s' in listener %d (%s:%d).\n",
6717 curproxy->id, listener->ssl_cert, listener->luid, listener->conf.file, listener->conf.line);
6718 cfgerr++;
6719 goto skip_ssl;
6720 }
6721 }
6722 skip_ssl:
6723#endif /* USE_OPENSSL */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006724 if (curproxy->options & PR_O_TCP_NOLING)
6725 listener->options |= LI_O_NOLINGER;
6726 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006727 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006728 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006729 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006730 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006731 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006732 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006733
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006734 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6735 listener->options |= LI_O_TCP_RULES;
6736
Willy Tarreaude3041d2010-05-31 10:56:17 +02006737 if (curproxy->mon_mask.s_addr)
6738 listener->options |= LI_O_CHK_MONNET;
6739
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006740 /* smart accept mode is automatic in HTTP mode */
6741 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6742 (curproxy->mode == PR_MODE_HTTP &&
6743 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6744 listener->options |= LI_O_NOQUICKACK;
6745
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006746 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006747 listener = listener->next;
6748 }
6749
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006750 /* Check multi-process mode compatibility for the current proxy */
6751 if (global.nbproc > 1) {
6752 int nbproc = 0;
6753 if (curproxy->bind_proc) {
6754 int proc;
6755 for (proc = 0; proc < global.nbproc; proc++) {
6756 if (curproxy->bind_proc & (1 << proc)) {
6757 nbproc++;
6758 }
6759 }
6760 } else {
6761 nbproc = global.nbproc;
6762 }
6763 if (curproxy->table.peers.name) {
6764 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6765 curproxy->id);
6766 cfgerr++;
6767 }
6768 if (nbproc > 1) {
6769 if (curproxy->uri_auth) {
6770 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6771 curproxy->id);
6772 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6773 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6774 curproxy->id);
6775 }
6776 }
6777 if (curproxy->appsession_name) {
6778 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6779 curproxy->id);
6780 }
6781 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6782 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6783 curproxy->id);
6784 }
6785 }
6786 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006787
6788 /* create the task associated with the proxy */
6789 curproxy->task = task_new();
6790 if (curproxy->task) {
6791 curproxy->task->context = curproxy;
6792 curproxy->task->process = manage_proxy;
6793 /* no need to queue, it will be done automatically if some
6794 * listener gets limited.
6795 */
6796 curproxy->task->expire = TICK_ETERNITY;
6797 } else {
6798 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6799 curproxy->id);
6800 cfgerr++;
6801 }
6802
Willy Tarreaubaaee002006-06-26 02:48:02 +02006803 curproxy = curproxy->next;
6804 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006805
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006806 /* Check multi-process mode compatibility */
6807 if (global.nbproc > 1) {
6808 if (global.stats_fe) {
6809 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6810 }
6811 }
6812
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6814 struct auth_users *curuser;
6815 int g;
6816
6817 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6818 unsigned int group_mask = 0;
6819 char *group = NULL;
6820
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006821 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006822 continue;
6823
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006824 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006825
6826 for (g = 0; g < curuserlist->grpcnt; g++)
6827 if (!strcmp(curuserlist->groups[g], group))
6828 break;
6829
6830 if (g == curuserlist->grpcnt) {
6831 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6832 curuserlist->name, group, curuser->user);
6833 err_code |= ERR_ALERT | ERR_FATAL;
6834 goto out;
6835 }
6836
6837 group_mask |= (1 << g);
6838 }
6839
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006840 free(curuser->u.groups);
6841 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006842 }
6843
6844 for (g = 0; g < curuserlist->grpcnt; g++) {
6845 char *user = NULL;
6846
6847 if (!curuserlist->groupusers[g])
6848 continue;
6849
6850 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6851 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6852 if (!strcmp(curuser->user, user))
6853 break;
6854
6855 if (!curuser) {
6856 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6857 curuserlist->name, user, curuserlist->groups[g]);
6858 err_code |= ERR_ALERT | ERR_FATAL;
6859 goto out;
6860 }
6861
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006862 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006863 }
6864
6865 free(curuserlist->groupusers[g]);
6866 }
6867
6868 free(curuserlist->groupusers);
6869
6870#ifdef DEBUG_AUTH
6871 for (g = 0; g < curuserlist->grpcnt; g++) {
6872 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6873
6874 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006875 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006876 fprintf(stderr, " %s", curuser->user);
6877 }
6878
6879 fprintf(stderr, "\n");
6880 }
6881#endif
6882
Willy Tarreaufbb78422011-06-05 15:38:35 +02006883 }
6884
6885 /* automatically compute fullconn if not set. We must not do it in the
6886 * loop above because cross-references are not yet fully resolved.
6887 */
6888 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6889 /* If <fullconn> is not set, let's set it to 10% of the sum of
6890 * the possible incoming frontend's maxconns.
6891 */
6892 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6893 struct proxy *fe;
6894 int total = 0;
6895
6896 /* sum up the number of maxconns of frontends which
6897 * reference this backend at least once or which are
6898 * the same one ('listen').
6899 */
6900 for (fe = proxy; fe; fe = fe->next) {
6901 struct switching_rule *rule;
6902 struct hdr_exp *exp;
6903 int found = 0;
6904
6905 if (!(fe->cap & PR_CAP_FE))
6906 continue;
6907
6908 if (fe == curproxy) /* we're on a "listen" instance */
6909 found = 1;
6910
6911 if (fe->defbe.be == curproxy) /* "default_backend" */
6912 found = 1;
6913
6914 /* check if a "use_backend" rule matches */
6915 if (!found) {
6916 list_for_each_entry(rule, &fe->switching_rules, list) {
6917 if (rule->be.backend == curproxy) {
6918 found = 1;
6919 break;
6920 }
6921 }
6922 }
6923
6924 /* check if a "reqsetbe" rule matches */
6925 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6926 if (exp->action == ACT_SETBE &&
6927 (struct proxy *)exp->replace == curproxy) {
6928 found = 1;
6929 break;
6930 }
6931 }
6932
6933 /* now we've checked all possible ways to reference a backend
6934 * from a frontend.
6935 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006936 if (!found)
6937 continue;
6938 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006939 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006940 /* we have the sum of the maxconns in <total>. We only
6941 * keep 10% of that sum to set the default fullconn, with
6942 * a hard minimum of 1 (to avoid a divide by zero).
6943 */
6944 curproxy->fullconn = (total + 9) / 10;
6945 if (!curproxy->fullconn)
6946 curproxy->fullconn = 1;
6947 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006948 }
6949
Willy Tarreau056f5682010-06-06 15:51:11 +02006950 /* initialize stick-tables on backend capable proxies. This must not
6951 * be done earlier because the data size may be discovered while parsing
6952 * other proxies.
6953 */
6954 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006955 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006956
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006957 /*
6958 * Recount currently required checks.
6959 */
6960
6961 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6962 int optnum;
6963
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006964 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6965 if (curproxy->options & cfg_opts[optnum].val)
6966 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006967
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006968 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6969 if (curproxy->options2 & cfg_opts2[optnum].val)
6970 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006971 }
6972
Willy Tarreau122541c2011-09-07 21:24:49 +02006973 if (peers) {
6974 struct peers *curpeers = peers, **last;
6975 struct peer *p, *pb;
6976
6977 /* Remove all peers sections which don't have a valid listener.
6978 * This can happen when a peers section is never referenced and
6979 * does not contain a local peer.
6980 */
6981 last = &peers;
6982 while (*last) {
6983 curpeers = *last;
6984 if (curpeers->peers_fe) {
6985 last = &curpeers->next;
6986 continue;
6987 }
6988
6989 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6990 curpeers->id, localpeer);
6991
6992 p = curpeers->remote;
6993 while (p) {
6994 pb = p->next;
6995 free(p->id);
6996 free(p);
6997 p = pb;
6998 }
6999
7000 /* Destroy and unlink this curpeers section.
7001 * Note: curpeers is backed up into *last.
7002 */
7003 free(curpeers->id);
7004 curpeers = curpeers->next;
7005 free(*last);
7006 *last = curpeers;
7007 }
7008 }
7009
Willy Tarreauac1932d2011-10-24 19:14:41 +02007010 if (!global.tune.max_http_hdr)
7011 global.tune.max_http_hdr = MAX_HTTP_HDR;
7012
Willy Tarreau34eb6712011-10-24 18:15:04 +02007013 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007014 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007015 MEM_F_SHARED);
7016
Willy Tarreaubb925012009-07-23 13:36:36 +02007017 if (cfgerr > 0)
7018 err_code |= ERR_ALERT | ERR_FATAL;
7019 out:
7020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021}
7022
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007023/*
7024 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7025 * parsing sessions.
7026 */
7027void cfg_register_keywords(struct cfg_kw_list *kwl)
7028{
7029 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7030}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007032/*
7033 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7034 */
7035void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7036{
7037 LIST_DEL(&kwl->list);
7038 LIST_INIT(&kwl->list);
7039}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007040
7041/*
7042 * Local variables:
7043 * c-indent-level: 8
7044 * c-basic-offset: 8
7045 * End:
7046 */