blob: ed64457625e925d75be3cf66cb052db61cdf436a [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>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 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 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
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.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200590 else if (!strcmp(args[0], "tune.pipesize")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.pipesize = atol(args[1]);
597 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 else if (!strcmp(args[0], "uid")) {
599 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200600 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200601 err_code |= ERR_ALERT;
602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 }
604 if (*(args[1]) == 0) {
605 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT | ERR_FATAL;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 global.uid = atol(args[1]);
610 }
611 else if (!strcmp(args[0], "gid")) {
612 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200613 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200621 }
622 global.gid = atol(args[1]);
623 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200624 /* user/group name handling */
625 else if (!strcmp(args[0], "user")) {
626 struct passwd *ha_user;
627 if (global.uid != 0) {
628 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT;
630 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 }
632 errno = 0;
633 ha_user = getpwnam(args[1]);
634 if (ha_user != NULL) {
635 global.uid = (int)ha_user->pw_uid;
636 }
637 else {
638 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 +0200639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 }
642 else if (!strcmp(args[0], "group")) {
643 struct group *ha_group;
644 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200645 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT;
647 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200648 }
649 errno = 0;
650 ha_group = getgrnam(args[1]);
651 if (ha_group != NULL) {
652 global.gid = (int)ha_group->gr_gid;
653 }
654 else {
655 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 +0200656 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 }
658 }
659 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200660 else if (!strcmp(args[0], "nbproc")) {
661 if (global.nbproc != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200663 err_code |= ERR_ALERT;
664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 global.nbproc = atol(args[1]);
672 }
673 else if (!strcmp(args[0], "maxconn")) {
674 if (global.maxconn != 0) {
675 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200676 err_code |= ERR_ALERT;
677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 }
679 if (*(args[1]) == 0) {
680 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT | ERR_FATAL;
682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200683 }
684 global.maxconn = atol(args[1]);
685#ifdef SYSTEM_MAXCONN
686 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
687 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);
688 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200690 }
691#endif /* SYSTEM_MAXCONN */
692 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200693 else if (!strcmp(args[0], "maxconnrate")) {
694 if (global.cps_lim != 0) {
695 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT;
697 goto out;
698 }
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.cps_lim = atol(args[1]);
705 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100706 else if (!strcmp(args[0], "maxpipes")) {
707 if (global.maxpipes != 0) {
708 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200709 err_code |= ERR_ALERT;
710 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100711 }
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 }
717 global.maxpipes = atol(args[1]);
718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200719 else if (!strcmp(args[0], "ulimit-n")) {
720 if (global.rlimit_nofile != 0) {
721 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200722 err_code |= ERR_ALERT;
723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200724 }
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 global.rlimit_nofile = atol(args[1]);
731 }
732 else if (!strcmp(args[0], "chroot")) {
733 if (global.chroot != NULL) {
734 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200735 err_code |= ERR_ALERT;
736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200737 }
738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200742 }
743 global.chroot = strdup(args[1]);
744 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200745 else if (!strcmp(args[0], "description")) {
746 int i, len=0;
747 char *d;
748
749 if (!*args[1]) {
750 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
751 file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755
756 for(i=1; *args[i]; i++)
757 len += strlen(args[i])+1;
758
759 if (global.desc)
760 free(global.desc);
761
762 global.desc = d = (char *)calloc(1, len);
763
764 d += sprintf(d, "%s", args[1]);
765 for(i=2; *args[i]; i++)
766 d += sprintf(d, " %s", args[i]);
767 }
768 else if (!strcmp(args[0], "node")) {
769 int i;
770 char c;
771
772 for (i=0; args[1][i]; i++) {
773 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100774 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
775 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200776 break;
777 }
778
779 if (!i || args[1][i]) {
780 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
781 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
782 file, linenum, args[0]);
783 err_code |= ERR_ALERT | ERR_FATAL;
784 goto out;
785 }
786
787 if (global.node)
788 free(global.node);
789
790 global.node = strdup(args[1]);
791 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 else if (!strcmp(args[0], "pidfile")) {
793 if (global.pidfile != NULL) {
794 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT;
796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200797 }
798 if (*(args[1]) == 0) {
799 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 }
803 global.pidfile = strdup(args[1]);
804 }
Emeric Bruned760922010-10-22 17:59:25 +0200805 else if (!strcmp(args[0], "unix-bind")) {
806 int cur_arg = 1;
807 while (*(args[cur_arg])) {
808 if (!strcmp(args[cur_arg], "prefix")) {
809 if (global.unix_bind.prefix != NULL) {
810 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
811 err_code |= ERR_ALERT;
812 cur_arg += 2;
813 continue;
814 }
815
816 if (*(args[cur_arg+1]) == 0) {
817 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
818 err_code |= ERR_ALERT | ERR_FATAL;
819 goto out;
820 }
821 global.unix_bind.prefix = strdup(args[cur_arg+1]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "mode")) {
827
828 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
829 cur_arg += 2;
830 continue;
831 }
832
833 if (!strcmp(args[cur_arg], "uid")) {
834
835 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
836 cur_arg += 2;
837 continue;
838 }
839
840 if (!strcmp(args[cur_arg], "gid")) {
841
842 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
843 cur_arg += 2;
844 continue;
845 }
846
847 if (!strcmp(args[cur_arg], "user")) {
848 struct passwd *user;
849
850 user = getpwnam(args[cur_arg + 1]);
851 if (!user) {
852 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
853 file, linenum, args[0], args[cur_arg + 1 ]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857
858 global.unix_bind.ux.uid = user->pw_uid;
859 cur_arg += 2;
860 continue;
861 }
862
863 if (!strcmp(args[cur_arg], "group")) {
864 struct group *group;
865
866 group = getgrnam(args[cur_arg + 1]);
867 if (!group) {
868 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
869 file, linenum, args[0], args[cur_arg + 1 ]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 global.unix_bind.ux.gid = group->gr_gid;
875 cur_arg += 2;
876 continue;
877 }
878
Willy Tarreaub48f9582011-09-05 01:17:06 +0200879 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200880 file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100886 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200887 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888
889 if (*(args[1]) == 0 || *(args[2]) == 0) {
890 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893 }
894
895 facility = get_log_facility(args[2]);
896 if (facility < 0) {
897 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901
902 level = 7; /* max syslog level = debug */
903 if (*(args[3])) {
904 level = get_log_level(args[3]);
905 if (level < 0) {
906 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200907 err_code |= ERR_ALERT | ERR_FATAL;
908 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 }
910 }
911
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200912 minlvl = 0; /* limit syslog level to this level (emerg) */
913 if (*(args[4])) {
914 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200916 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200919 }
920 }
921
Robert Tsai81ae1952007-12-05 10:47:29 +0100922 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100923 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100924 if (!sk) {
925 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100926 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
929 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100930 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100931 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100932 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100933 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100934 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
935 err_code |= ERR_ALERT | ERR_FATAL;
936 goto out;
937 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100938 logsrv.addr = *sk;
939 if (!get_host_port(&logsrv.addr))
940 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942
943 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100944 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 global.logfac1 = facility;
946 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200947 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
949 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100950 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 global.logfac2 = facility;
952 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200953 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 }
955 else {
956 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200957 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200959 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100960 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
961 char *name;
962 int len;
963
964 if (global.log_send_hostname != NULL) {
965 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT;
967 goto out;
968 }
969
970 if (*(args[1]))
971 name = args[1];
972 else
973 name = hostname;
974
975 len = strlen(name);
976
977 /* We'll add a space after the name to respect the log format */
978 free(global.log_send_hostname);
979 global.log_send_hostname = malloc(len + 2);
980 snprintf(global.log_send_hostname, len + 2, "%s ", name);
981 }
Kevinm48936af2010-12-22 16:08:21 +0000982 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
983 if (*(args[1]) == 0) {
984 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988 free(global.log_tag);
989 global.log_tag = strdup(args[1]);
990 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200991 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
992 if (global.spread_checks != 0) {
993 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200994 err_code |= ERR_ALERT;
995 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200996 }
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001001 }
1002 global.spread_checks = atol(args[1]);
1003 if (global.spread_checks < 0 || global.spread_checks > 50) {
1004 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007 }
1008 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001009 struct cfg_kw_list *kwl;
1010 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001011 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001012
1013 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1014 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1015 if (kwl->kw[index].section != CFG_GLOBAL)
1016 continue;
1017 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1018 /* prepare error message just in case */
1019 snprintf(trash, sizeof(trash),
1020 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001021 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1022 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001024 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001026 else if (rc > 0) {
1027 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001028 err_code |= ERR_WARN;
1029 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001031 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 }
1033 }
1034 }
1035
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001038 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001039
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 out:
1041 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042}
1043
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001044void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001046 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 defproxy.mode = PR_MODE_TCP;
1048 defproxy.state = PR_STNEW;
1049 defproxy.maxconn = cfg_maxpconn;
1050 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001051
1052 defproxy.defsrv.inter = DEF_CHKINTR;
1053 defproxy.defsrv.fastinter = 0;
1054 defproxy.defsrv.downinter = 0;
1055 defproxy.defsrv.rise = DEF_RISETIME;
1056 defproxy.defsrv.fall = DEF_FALLTIME;
1057 defproxy.defsrv.check_port = 0;
1058 defproxy.defsrv.maxqueue = 0;
1059 defproxy.defsrv.minconn = 0;
1060 defproxy.defsrv.maxconn = 0;
1061 defproxy.defsrv.slowstart = 0;
1062 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1063 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1064 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065}
1066
Willy Tarreauade5ec42010-01-28 19:33:49 +01001067
1068static int create_cond_regex_rule(const char *file, int line,
1069 struct proxy *px, int dir, int action, int flags,
1070 const char *cmd, const char *reg, const char *repl,
1071 const char **cond_start)
1072{
1073 regex_t *preg = NULL;
1074 const char *err;
1075 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001076 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001077
1078 if (px == &defproxy) {
1079 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto err;
1082 }
1083
1084 if (*reg == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto err;
1088 }
1089
1090 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1091 err_code |= ERR_WARN;
1092
Willy Tarreau5321c422010-01-28 20:35:13 +01001093 if (cond_start &&
1094 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1095 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1096 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1097 file, line, cmd);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto err;
1100 }
1101 }
1102 else if (cond_start && **cond_start) {
1103 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1104 file, line, cmd, *cond_start);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto err;
1107 }
1108
1109 if (dir == ACL_DIR_REQ)
1110 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001111 else
1112 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001113
Willy Tarreauade5ec42010-01-28 19:33:49 +01001114 preg = calloc(1, sizeof(regex_t));
1115 if (!preg) {
1116 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1117 err_code = ERR_ALERT | ERR_FATAL;
1118 goto err;
1119 }
1120
1121 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1122 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1123 err_code = ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001128 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001129 if (repl && err) {
1130 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1131 file, line, cmd, *err);
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto err;
1134 }
1135
1136 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1137 err_code |= ERR_WARN;
1138
1139 return err_code;
1140 err:
1141 free(preg);
1142 return err_code;
1143}
1144
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001146 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001147 * Returns the error code, 0 if OK, or any combination of :
1148 * - ERR_ABORT: must abort ASAP
1149 * - ERR_FATAL: we can continue parsing but not start the service
1150 * - ERR_WARN: a warning has been emitted
1151 * - ERR_ALERT: an alert has been emitted
1152 * Only the two first ones can stop processing, the two others are just
1153 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001155int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1156{
1157 static struct peers *curpeers = NULL;
1158 struct peer *newpeer = NULL;
1159 const char *err;
1160 int err_code = 0;
1161
1162 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1163
1164 err = invalid_char(args[1]);
1165 if (err) {
1166 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1167 file, linenum, *err, args[0], args[1]);
1168 err_code |= ERR_ALERT | ERR_FATAL;
1169 }
1170
1171 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1172 /*
1173 * If there are two proxies with the same name only following
1174 * combinations are allowed:
1175 */
1176 if (strcmp(curpeers->id, args[1]) == 0) {
1177 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1178 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1179 err_code |= ERR_WARN;
1180 }
1181 }
1182
1183 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1185 err_code |= ERR_ALERT | ERR_ABORT;
1186 goto out;
1187 }
1188
1189 curpeers->next = peers;
1190 peers = curpeers;
1191 curpeers->conf.file = file;
1192 curpeers->conf.line = linenum;
1193 curpeers->last_change = now.tv_sec;
1194 curpeers->id = strdup(args[1]);
1195 }
1196 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1197 char *rport, *raddr;
1198 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001199 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001200
1201 if (!*args[2]) {
1202 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1203 file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207
1208 err = invalid_char(args[1]);
1209 if (err) {
1210 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1211 file, linenum, *err, args[1]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214 }
1215
1216 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1218 err_code |= ERR_ALERT | ERR_ABORT;
1219 goto out;
1220 }
1221
1222 /* the peers are linked backwards first */
1223 curpeers->count++;
1224 newpeer->next = curpeers->remote;
1225 curpeers->remote = newpeer;
1226 newpeer->peers = curpeers;
1227 newpeer->conf.file = file;
1228 newpeer->conf.line = linenum;
1229
1230 newpeer->last_change = now.tv_sec;
1231 newpeer->id = strdup(args[1]);
1232
1233 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001234 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001235 if (rport) {
1236 *rport++ = 0;
1237 realport = atol(rport);
1238 }
1239 if (!realport) {
1240 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1241 err_code |= ERR_ALERT | ERR_FATAL;
1242 goto out;
1243 }
1244
Willy Tarreaufab5a432011-03-04 15:31:53 +01001245 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001246 free(raddr);
1247 if (!sk) {
1248 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001253 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001254
1255 if (strcmp(newpeer->id, localpeer) == 0) {
1256 /* Current is local peer, it define a frontend */
1257 newpeer->local = 1;
1258
1259 if (!curpeers->peers_fe) {
1260 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1261 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1262 err_code |= ERR_ALERT | ERR_ABORT;
1263 goto out;
1264 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001265
Willy Tarreau237250c2011-07-29 01:49:03 +02001266 init_new_proxy(curpeers->peers_fe);
1267 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001268
1269 curpeers->peers_fe->last_change = now.tv_sec;
1270 curpeers->peers_fe->id = strdup(args[1]);
1271 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001272 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001273 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1274 curpeers->peers_fe->timeout.connect = 5000;
1275 curpeers->peers_fe->accept = peer_accept;
1276 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001277 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001278 err_code |= ERR_FATAL;
1279 goto out;
1280 }
1281 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1282 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1283 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1284 curpeers->peers_fe->listen->accept = session_accept;
1285 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1286 curpeers->peers_fe->listen->handler = process_session;
1287 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001288 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1289 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001290 }
1291 }
1292 } /* neither "peer" nor "peers" */
1293 else if (*args[0] != 0) {
1294 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298
1299out:
1300 return err_code;
1301}
1302
1303
Willy Tarreau3842f002009-06-14 11:39:52 +02001304int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001305{
1306 static struct proxy *curproxy = NULL;
1307 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001308 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001309 int rc;
1310 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001311 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001312 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313
Willy Tarreau977b8e42006-12-29 14:19:17 +01001314 if (!strcmp(args[0], "listen"))
1315 rc = PR_CAP_LISTEN;
1316 else if (!strcmp(args[0], "frontend"))
1317 rc = PR_CAP_FE | PR_CAP_RS;
1318 else if (!strcmp(args[0], "backend"))
1319 rc = PR_CAP_BE | PR_CAP_RS;
1320 else if (!strcmp(args[0], "ruleset"))
1321 rc = PR_CAP_RS;
1322 else
1323 rc = PR_CAP_NONE;
1324
1325 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 if (!*args[1]) {
1327 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1328 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001330 err_code |= ERR_ALERT | ERR_ABORT;
1331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001333
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001334 err = invalid_char(args[1]);
1335 if (err) {
1336 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1337 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001338 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001339 }
1340
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001341 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1342 /*
1343 * If there are two proxies with the same name only following
1344 * combinations are allowed:
1345 *
1346 * listen backend frontend ruleset
1347 * listen - - - -
1348 * backend - - OK -
1349 * frontend - OK - -
1350 * ruleset - - - -
1351 */
1352
1353 if (!strcmp(curproxy->id, args[1]) &&
1354 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1355 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001356 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1357 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1358 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001359 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001360 }
1361 }
1362
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1364 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_ABORT;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001368
Willy Tarreau97cb7802010-01-03 20:23:58 +01001369 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 curproxy->next = proxy;
1371 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001372 curproxy->conf.file = file;
1373 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001374 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001375 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001376 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377
1378 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001379 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001380 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001381 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_FATAL;
1383 goto out;
1384 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001385 new = curproxy->listen;
1386 while (new != last) {
1387 new->conf.file = file;
1388 new->conf.line = linenum;
1389 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001390 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 }
1393
1394 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001395 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001396 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001400 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001401 curproxy->no_options = defproxy.no_options;
1402 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001403 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001404 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001405 curproxy->except_net = defproxy.except_net;
1406 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001407 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001408 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001410 if (defproxy.fwdfor_hdr_len) {
1411 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1412 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1413 }
1414
Willy Tarreaub86db342009-11-30 11:50:16 +01001415 if (defproxy.orgto_hdr_len) {
1416 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1417 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1418 }
1419
Willy Tarreau977b8e42006-12-29 14:19:17 +01001420 if (curproxy->cap & PR_CAP_FE) {
1421 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001422 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001423 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001424
1425 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001426 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1427 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001428
1429 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431
Willy Tarreau977b8e42006-12-29 14:19:17 +01001432 if (curproxy->cap & PR_CAP_BE) {
1433 curproxy->fullconn = defproxy.fullconn;
1434 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001436 if (defproxy.check_req) {
1437 curproxy->check_req = calloc(1, defproxy.check_len);
1438 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1439 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001440 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001442 if (defproxy.expect_str) {
1443 curproxy->expect_str = strdup(defproxy.expect_str);
1444 if (defproxy.expect_regex) {
1445 /* note: this regex is known to be valid */
1446 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1447 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1448 }
1449 }
1450
Willy Tarreau977b8e42006-12-29 14:19:17 +01001451 if (defproxy.cookie_name)
1452 curproxy->cookie_name = strdup(defproxy.cookie_name);
1453 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001454 if (defproxy.cookie_domain)
1455 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001456
Willy Tarreau31936852010-10-06 16:59:56 +02001457 if (defproxy.cookie_maxidle)
1458 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1459
1460 if (defproxy.cookie_maxlife)
1461 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1462
Emeric Brun647caf12009-06-30 17:57:00 +02001463 if (defproxy.rdp_cookie_name)
1464 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1465 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1466
Willy Tarreau01732802007-11-01 22:48:15 +01001467 if (defproxy.url_param_name)
1468 curproxy->url_param_name = strdup(defproxy.url_param_name);
1469 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001470
Benoitaffb4812009-03-25 13:02:10 +01001471 if (defproxy.hh_name)
1472 curproxy->hh_name = strdup(defproxy.hh_name);
1473 curproxy->hh_len = defproxy.hh_len;
1474 curproxy->hh_match_domain = defproxy.hh_match_domain;
1475
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001476 if (defproxy.iface_name)
1477 curproxy->iface_name = strdup(defproxy.iface_name);
1478 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001480
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001481 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001482 if (defproxy.capture_name)
1483 curproxy->capture_name = strdup(defproxy.capture_name);
1484 curproxy->capture_namelen = defproxy.capture_namelen;
1485 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487
Willy Tarreau977b8e42006-12-29 14:19:17 +01001488 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001489 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001490 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001491 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001492 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 curproxy->uri_auth = defproxy.uri_auth;
1494 curproxy->mon_net = defproxy.mon_net;
1495 curproxy->mon_mask = defproxy.mon_mask;
1496 if (defproxy.monitor_uri)
1497 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1498 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001499 if (defproxy.defbe.name)
1500 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 }
1502
1503 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001504 curproxy->timeout.connect = defproxy.timeout.connect;
1505 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001506 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001507 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001508 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001509 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001510 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001511 curproxy->source_addr = defproxy.source_addr;
1512 }
1513
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 curproxy->mode = defproxy.mode;
1515 curproxy->logfac1 = defproxy.logfac1;
1516 curproxy->logsrv1 = defproxy.logsrv1;
1517 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001518 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 curproxy->logfac2 = defproxy.logfac2;
1520 curproxy->logsrv2 = defproxy.logsrv2;
1521 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001522 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001524 curproxy->conf.used_listener_id = EB_ROOT;
1525 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001526
Willy Tarreau93893792009-07-23 13:19:11 +02001527 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 }
1529 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1530 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001531 /* FIXME-20070101: we should do this too at the end of the
1532 * config parsing to free all default values.
1533 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001534 free(defproxy.check_req);
1535 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001536 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001537 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001538 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001539 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001540 free(defproxy.capture_name);
1541 free(defproxy.monitor_uri);
1542 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001543 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001544 free(defproxy.fwdfor_hdr_name);
1545 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001546 free(defproxy.orgto_hdr_name);
1547 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001548 free(defproxy.expect_str);
1549 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001550
Willy Tarreaua534fea2008-08-03 12:19:50 +02001551 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001552 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001553
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 /* we cannot free uri_auth because it might already be used */
1555 init_default_instance();
1556 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 }
1560 else if (curproxy == NULL) {
1561 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001562 err_code |= ERR_ALERT | ERR_FATAL;
1563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 }
1565
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566
1567 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001569 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001570 int cur_arg;
1571
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 if (curproxy == &defproxy) {
1573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001578 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579
Emeric Bruned760922010-10-22 17:59:25 +02001580 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001581 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001586
1587 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001588
1589 /* NOTE: the following line might create several listeners if there
1590 * are comma-separated IPs or port ranges. So all further processing
1591 * will have to be applied to all listeners created after last_listen.
1592 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001593 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
1596 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001597
Willy Tarreau90a570f2009-10-04 20:54:54 +02001598 new_listen = curproxy->listen;
1599 while (new_listen != last_listen) {
1600 new_listen->conf.file = file;
1601 new_listen->conf.line = linenum;
1602 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001603 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001604 }
1605
Emeric Bruned760922010-10-22 17:59:25 +02001606 /* Set default global rights and owner for unix bind */
1607 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1608 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1609 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001610 cur_arg = 2;
1611 while (*(args[cur_arg])) {
1612 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1613#ifdef SO_BINDTODEVICE
1614 struct listener *l;
1615
Emeric Bruned760922010-10-22 17:59:25 +02001616 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1617 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1618 file, linenum, args[0], args[cur_arg]);
1619 err_code |= ERR_ALERT | ERR_FATAL;
1620 goto out;
1621 }
1622
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001623 if (!*args[cur_arg + 1]) {
1624 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1625 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001628 }
1629
1630 for (l = curproxy->listen; l != last_listen; l = l->next)
1631 l->interface = strdup(args[cur_arg + 1]);
1632
1633 global.last_checks |= LSTCHK_NETADM;
1634
1635 cur_arg += 2;
1636 continue;
1637#else
1638 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1639 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_FATAL;
1641 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001642#endif
1643 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001644 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1645#ifdef TCP_MAXSEG
1646 struct listener *l;
1647 int mss;
1648
Emeric Bruned760922010-10-22 17:59:25 +02001649 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1650 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1651 file, linenum, args[0], args[cur_arg]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655
Willy Tarreaube1b9182009-06-14 18:48:19 +02001656 if (!*args[cur_arg + 1]) {
1657 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1658 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001661 }
1662
Willy Tarreau48a7e722010-12-24 15:26:39 +01001663 mss = atoi(args[cur_arg + 1]);
1664 if (!mss || abs(mss) > 65535) {
1665 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001666 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001669 }
1670
1671 for (l = curproxy->listen; l != last_listen; l = l->next)
1672 l->maxseg = mss;
1673
1674 cur_arg += 2;
1675 continue;
1676#else
1677 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1678 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001679 err_code |= ERR_ALERT | ERR_FATAL;
1680 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001681#endif
1682 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001683
1684 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1685#ifdef TCP_DEFER_ACCEPT
1686 struct listener *l;
1687
1688 for (l = curproxy->listen; l != last_listen; l = l->next)
1689 l->options |= LI_O_DEF_ACCEPT;
1690
1691 cur_arg ++;
1692 continue;
1693#else
1694 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1695 file, linenum, args[0], args[cur_arg]);
1696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
1698#endif
1699 }
1700
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001701 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001702#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001703 struct listener *l;
1704
Emeric Bruned760922010-10-22 17:59:25 +02001705 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1706 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1707 file, linenum, args[0], args[cur_arg]);
1708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
1710 }
1711
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001712 for (l = curproxy->listen; l != last_listen; l = l->next)
1713 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001714
1715 cur_arg ++;
1716 continue;
1717#else
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1719 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001722#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001723 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001724
Willy Tarreau8a956912010-10-15 14:27:08 +02001725 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1726 struct listener *l;
1727
1728 for (l = curproxy->listen; l != last_listen; l = l->next)
1729 l->options |= LI_O_ACC_PROXY;
1730
1731 cur_arg ++;
1732 continue;
1733 }
1734
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001735 if (!strcmp(args[cur_arg], "name")) {
1736 struct listener *l;
1737
1738 for (l = curproxy->listen; l != last_listen; l = l->next)
1739 l->name = strdup(args[cur_arg + 1]);
1740
1741 cur_arg += 2;
1742 continue;
1743 }
1744
1745 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001746 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001747 struct listener *l;
1748
1749 if (curproxy->listen->next != last_listen) {
1750 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1751 file, linenum, args[cur_arg]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
1756 if (!*args[cur_arg + 1]) {
1757 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1758 file, linenum, args[cur_arg]);
1759 err_code |= ERR_ALERT | ERR_FATAL;
1760 goto out;
1761 }
1762
1763 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001764 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001765
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001766 if (curproxy->listen->luid <= 0) {
1767 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001768 file, linenum);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001773 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1774 if (node) {
1775 l = container_of(node, struct listener, conf.id);
1776 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1777 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
1780 }
1781 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1782
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001783 cur_arg += 2;
1784 continue;
1785 }
1786
Emeric Bruned760922010-10-22 17:59:25 +02001787 if (!strcmp(args[cur_arg], "mode")) {
1788
1789 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1790 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1791 file, linenum, args[0], args[cur_arg]);
1792 err_code |= ERR_ALERT | ERR_FATAL;
1793 goto out;
1794 }
1795
1796 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1797
1798 cur_arg += 2;
1799 continue;
1800 }
1801
1802 if (!strcmp(args[cur_arg], "uid")) {
1803
1804 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1805 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1806 file, linenum, args[0], args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1812 cur_arg += 2;
1813 continue;
1814 }
1815
1816 if (!strcmp(args[cur_arg], "gid")) {
1817
1818 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1819 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1820 file, linenum, args[0], args[cur_arg]);
1821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
1824
1825 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1826 cur_arg += 2;
1827 continue;
1828 }
1829
1830 if (!strcmp(args[cur_arg], "user")) {
1831 struct passwd *user;
1832
1833 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1834 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1835 file, linenum, args[0], args[cur_arg]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839 user = getpwnam(args[cur_arg + 1]);
1840 if (!user) {
1841 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1842 file, linenum, args[0], args[cur_arg + 1 ]);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
1846
1847 curproxy->listen->perm.ux.uid = user->pw_uid;
1848 cur_arg += 2;
1849 continue;
1850 }
1851
1852 if (!strcmp(args[cur_arg], "group")) {
1853 struct group *group;
1854
1855 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1856 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1857 file, linenum, args[0], args[cur_arg]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 group = getgrnam(args[cur_arg + 1]);
1862 if (!group) {
1863 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1864 file, linenum, args[0], args[cur_arg + 1 ]);
1865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
1867 }
1868
1869 curproxy->listen->perm.ux.gid = group->gr_gid;
1870 cur_arg += 2;
1871 continue;
1872 }
1873
Willy Tarreaub48f9582011-09-05 01:17:06 +02001874 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 +01001875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001878 }
Willy Tarreau93893792009-07-23 13:19:11 +02001879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 }
1881 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1882 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1883 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001887 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 /* flush useless bits */
1892 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001895 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898
Willy Tarreau1c47f852006-07-09 08:22:27 +02001899 if (!*args[1]) {
1900 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001904 }
1905
Willy Tarreaua534fea2008-08-03 12:19:50 +02001906 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001907 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001908 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001909 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1911
Willy Tarreau93893792009-07-23 13:19:11 +02001912 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001914 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1915 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1916 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1917 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1918 else {
1919 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 }
1923 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001924 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001925 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001926
1927 if (curproxy == &defproxy) {
1928 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1929 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001932 }
1933
1934 if (!*args[1]) {
1935 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1936 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001937 err_code |= ERR_ALERT | ERR_FATAL;
1938 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001939 }
1940
1941 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001942 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001943
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001944 if (curproxy->uuid <= 0) {
1945 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001946 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001949 }
1950
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001951 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1952 if (node) {
1953 struct proxy *target = container_of(node, struct proxy, conf.id);
1954 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1955 file, linenum, proxy_type_str(curproxy), curproxy->id,
1956 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1957 err_code |= ERR_ALERT | ERR_FATAL;
1958 goto out;
1959 }
1960 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001961 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001962 else if (!strcmp(args[0], "description")) {
1963 int i, len=0;
1964 char *d;
1965
Cyril Bonté99ed3272010-01-24 23:29:44 +01001966 if (curproxy == &defproxy) {
1967 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1968 file, linenum, args[0]);
1969 err_code |= ERR_ALERT | ERR_FATAL;
1970 goto out;
1971 }
1972
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001973 if (!*args[1]) {
1974 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1975 file, linenum, args[0]);
1976 return -1;
1977 }
1978
1979 for(i=1; *args[i]; i++)
1980 len += strlen(args[i])+1;
1981
1982 d = (char *)calloc(1, len);
1983 curproxy->desc = d;
1984
1985 d += sprintf(d, "%s", args[1]);
1986 for(i=2; *args[i]; i++)
1987 d += sprintf(d, " %s", args[i]);
1988
1989 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001990 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1991 curproxy->state = PR_STSTOPPED;
1992 }
1993 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1994 curproxy->state = PR_STNEW;
1995 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001996 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1997 int cur_arg = 1;
1998 unsigned int set = 0;
1999
2000 while (*args[cur_arg]) {
2001 int u;
2002 if (strcmp(args[cur_arg], "all") == 0) {
2003 set = 0;
2004 break;
2005 }
2006 else if (strcmp(args[cur_arg], "odd") == 0) {
2007 set |= 0x55555555;
2008 }
2009 else if (strcmp(args[cur_arg], "even") == 0) {
2010 set |= 0xAAAAAAAA;
2011 }
2012 else {
2013 u = str2uic(args[cur_arg]);
2014 if (u < 1 || u > 32) {
2015 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2016 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002019 }
2020 if (u > global.nbproc) {
2021 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2022 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002023 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002024 }
2025 set |= 1 << (u - 1);
2026 }
2027 cur_arg++;
2028 }
2029 curproxy->bind_proc = set;
2030 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002031 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002032 if (curproxy == &defproxy) {
2033 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002036 }
2037
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002038 err = invalid_char(args[1]);
2039 if (err) {
2040 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2041 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002042 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002043 }
2044
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002045 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2046 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2047 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002050 }
2051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2053 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054
Willy Tarreau977b8e42006-12-29 14:19:17 +01002055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057
Willy Tarreaubaaee002006-06-26 02:48:02 +02002058 if (*(args[1]) == 0) {
2059 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002064
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002065 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002066 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002067 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002068 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002069 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 curproxy->cookie_name = strdup(args[1]);
2071 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002072
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 cur_arg = 2;
2074 while (*(args[cur_arg])) {
2075 if (!strcmp(args[cur_arg], "rewrite")) {
2076 curproxy->options |= PR_O_COOK_RW;
2077 }
2078 else if (!strcmp(args[cur_arg], "indirect")) {
2079 curproxy->options |= PR_O_COOK_IND;
2080 }
2081 else if (!strcmp(args[cur_arg], "insert")) {
2082 curproxy->options |= PR_O_COOK_INS;
2083 }
2084 else if (!strcmp(args[cur_arg], "nocache")) {
2085 curproxy->options |= PR_O_COOK_NOC;
2086 }
2087 else if (!strcmp(args[cur_arg], "postonly")) {
2088 curproxy->options |= PR_O_COOK_POST;
2089 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002090 else if (!strcmp(args[cur_arg], "preserve")) {
2091 curproxy->options2 |= PR_O2_COOK_PSV;
2092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 else if (!strcmp(args[cur_arg], "prefix")) {
2094 curproxy->options |= PR_O_COOK_PFX;
2095 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002096 else if (!strcmp(args[cur_arg], "domain")) {
2097 if (!*args[cur_arg + 1]) {
2098 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2099 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_ALERT | ERR_FATAL;
2101 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002102 }
2103
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002104 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002105 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002106 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2107 " dots nor does not start with a dot."
2108 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002109 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002110 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 }
2112
2113 err = invalid_domainchar(args[cur_arg + 1]);
2114 if (err) {
2115 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2116 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002117 err_code |= ERR_ALERT | ERR_FATAL;
2118 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002119 }
2120
Willy Tarreau68a897b2009-12-03 23:28:34 +01002121 if (!curproxy->cookie_domain) {
2122 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2123 } else {
2124 /* one domain was already specified, add another one by
2125 * building the string which will be returned along with
2126 * the cookie.
2127 */
2128 char *new_ptr;
2129 int new_len = strlen(curproxy->cookie_domain) +
2130 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2131 new_ptr = malloc(new_len);
2132 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2133 free(curproxy->cookie_domain);
2134 curproxy->cookie_domain = new_ptr;
2135 }
Willy Tarreau31936852010-10-06 16:59:56 +02002136 cur_arg++;
2137 }
2138 else if (!strcmp(args[cur_arg], "maxidle")) {
2139 unsigned int maxidle;
2140 const char *res;
2141
2142 if (!*args[cur_arg + 1]) {
2143 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2144 file, linenum, args[cur_arg]);
2145 err_code |= ERR_ALERT | ERR_FATAL;
2146 goto out;
2147 }
2148
2149 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2150 if (res) {
2151 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2152 file, linenum, *res, args[cur_arg]);
2153 err_code |= ERR_ALERT | ERR_FATAL;
2154 goto out;
2155 }
2156 curproxy->cookie_maxidle = maxidle;
2157 cur_arg++;
2158 }
2159 else if (!strcmp(args[cur_arg], "maxlife")) {
2160 unsigned int maxlife;
2161 const char *res;
2162
2163 if (!*args[cur_arg + 1]) {
2164 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2165 file, linenum, args[cur_arg]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169
2170 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2171 if (res) {
2172 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2173 file, linenum, *res, args[cur_arg]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
2177 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002178 cur_arg++;
2179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002180 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002181 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 +02002182 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 }
2186 cur_arg++;
2187 }
2188 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2189 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2190 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
2193
2194 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2195 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2196 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002199
2200 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2201 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2202 file, linenum);
2203 err_code |= ERR_ALERT | ERR_FATAL;
2204 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002206 else if (!strcmp(args[0], "persist")) { /* persist */
2207 if (*(args[1]) == 0) {
2208 Alert("parsing [%s:%d] : missing persist method.\n",
2209 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002212 }
2213
2214 if (!strncmp(args[1], "rdp-cookie", 10)) {
2215 curproxy->options2 |= PR_O2_RDPC_PRST;
2216
Emeric Brunb982a3d2010-01-04 15:45:53 +01002217 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002218 const char *beg, *end;
2219
2220 beg = args[1] + 11;
2221 end = strchr(beg, ')');
2222
2223 if (!end || end == beg) {
2224 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2225 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002228 }
2229
2230 free(curproxy->rdp_cookie_name);
2231 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2232 curproxy->rdp_cookie_len = end-beg;
2233 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002234 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002235 free(curproxy->rdp_cookie_name);
2236 curproxy->rdp_cookie_name = strdup("msts");
2237 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2238 }
2239 else { /* syntax */
2240 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2241 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002244 }
2245 }
2246 else {
2247 Alert("parsing [%s:%d] : unknown persist method.\n",
2248 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002251 }
2252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002254 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002256 if (curproxy == &defproxy) {
2257 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
2260 }
2261
Willy Tarreau977b8e42006-12-29 14:19:17 +01002262 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002263 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002264
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002266 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
2271 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002272 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 curproxy->appsession_name = strdup(args[1]);
2274 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2275 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002276 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2277 if (err) {
2278 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2279 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002282 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002283 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002284
Willy Tarreau51041c72007-09-09 21:56:53 +02002285 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2286 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_ALERT | ERR_ABORT;
2288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002290
2291 cur_arg = 6;
2292 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002293 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2294 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002295 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002296 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002297 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002298 } else if (!strcmp(args[cur_arg], "prefix")) {
2299 curproxy->options2 |= PR_O2_AS_PFX;
2300 } else if (!strcmp(args[cur_arg], "mode")) {
2301 if (!*args[cur_arg + 1]) {
2302 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2303 file, linenum, args[0], args[cur_arg]);
2304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
2307
2308 cur_arg++;
2309 if (!strcmp(args[cur_arg], "query-string")) {
2310 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2311 curproxy->options2 |= PR_O2_AS_M_QS;
2312 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2313 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2314 curproxy->options2 |= PR_O2_AS_M_PP;
2315 } else {
2316 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002321 cur_arg++;
2322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 } /* Url App Session */
2324 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002325 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002329 if (curproxy == &defproxy) {
2330 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2331 err_code |= ERR_ALERT | ERR_FATAL;
2332 goto out;
2333 }
2334
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 if (*(args[4]) == 0) {
2336 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002341 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 curproxy->capture_name = strdup(args[2]);
2343 curproxy->capture_namelen = strlen(curproxy->capture_name);
2344 curproxy->capture_len = atol(args[4]);
2345 if (curproxy->capture_len >= CAPTURE_LEN) {
2346 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2347 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 curproxy->capture_len = CAPTURE_LEN - 1;
2350 }
2351 curproxy->to_log |= LW_COOKIE;
2352 }
2353 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2354 struct cap_hdr *hdr;
2355
2356 if (curproxy == &defproxy) {
2357 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 +02002358 err_code |= ERR_ALERT | ERR_FATAL;
2359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
2361
2362 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2363 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2364 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 }
2368
2369 hdr = calloc(sizeof(struct cap_hdr), 1);
2370 hdr->next = curproxy->req_cap;
2371 hdr->name = strdup(args[3]);
2372 hdr->namelen = strlen(args[3]);
2373 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002374 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 hdr->index = curproxy->nb_req_cap++;
2376 curproxy->req_cap = hdr;
2377 curproxy->to_log |= LW_REQHDR;
2378 }
2379 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2380 struct cap_hdr *hdr;
2381
2382 if (curproxy == &defproxy) {
2383 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 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 }
2387
2388 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2389 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2390 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_ALERT | ERR_FATAL;
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394 hdr = calloc(sizeof(struct cap_hdr), 1);
2395 hdr->next = curproxy->rsp_cap;
2396 hdr->name = strdup(args[3]);
2397 hdr->namelen = strlen(args[3]);
2398 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002399 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 hdr->index = curproxy->nb_rsp_cap++;
2401 curproxy->rsp_cap = hdr;
2402 curproxy->to_log |= LW_RSPHDR;
2403 }
2404 else {
2405 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2406 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
2410 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002412 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002414
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 if (*(args[1]) == 0) {
2416 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
2421 curproxy->conn_retries = atol(args[1]);
2422 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002423 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002424 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425
2426 if (curproxy == &defproxy) {
2427 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431
Willy Tarreauff011f22011-01-06 17:51:27 +01002432 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 +01002433 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_WARN;
2436 }
2437
Willy Tarreauff011f22011-01-06 17:51:27 +01002438 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002439
Willy Tarreauff011f22011-01-06 17:51:27 +01002440 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002441 err_code |= ERR_ALERT | ERR_ABORT;
2442 goto out;
2443 }
2444
Willy Tarreauff011f22011-01-06 17:51:27 +01002445 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2446 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002447 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002448 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002449 if (curproxy == &defproxy) {
2450 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002453 }
2454
Willy Tarreauef6494c2010-01-28 17:12:36 +01002455 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002456 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2457 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002458 err_code |= ERR_ALERT | ERR_FATAL;
2459 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002460 }
2461
Willy Tarreauef6494c2010-01-28 17:12:36 +01002462 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002463 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2464 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002467 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002468
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002469 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002470 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002471 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002472 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002473 struct redirect_rule *rule;
2474 int cur_arg;
2475 int type = REDIRECT_TYPE_NONE;
2476 int code = 302;
2477 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002478 char *cookie = NULL;
2479 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002480 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002481
Cyril Bonté99ed3272010-01-24 23:29:44 +01002482 if (curproxy == &defproxy) {
2483 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
2486 }
2487
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002488 cur_arg = 1;
2489 while (*(args[cur_arg])) {
2490 if (!strcmp(args[cur_arg], "location")) {
2491 if (!*args[cur_arg + 1]) {
2492 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2493 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002496 }
2497
2498 type = REDIRECT_TYPE_LOCATION;
2499 cur_arg++;
2500 destination = args[cur_arg];
2501 }
2502 else if (!strcmp(args[cur_arg], "prefix")) {
2503 if (!*args[cur_arg + 1]) {
2504 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2505 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002508 }
2509
2510 type = REDIRECT_TYPE_PREFIX;
2511 cur_arg++;
2512 destination = args[cur_arg];
2513 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002514 else if (!strcmp(args[cur_arg], "set-cookie")) {
2515 if (!*args[cur_arg + 1]) {
2516 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2517 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002520 }
2521
2522 cur_arg++;
2523 cookie = args[cur_arg];
2524 cookie_set = 1;
2525 }
2526 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2527 if (!*args[cur_arg + 1]) {
2528 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2529 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002532 }
2533
2534 cur_arg++;
2535 cookie = args[cur_arg];
2536 cookie_set = 0;
2537 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002538 else if (!strcmp(args[cur_arg],"code")) {
2539 if (!*args[cur_arg + 1]) {
2540 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2541 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002544 }
2545 cur_arg++;
2546 code = atol(args[cur_arg]);
2547 if (code < 301 || code > 303) {
2548 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2549 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002552 }
2553 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002554 else if (!strcmp(args[cur_arg],"drop-query")) {
2555 flags |= REDIRECT_FLAG_DROP_QS;
2556 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002557 else if (!strcmp(args[cur_arg],"append-slash")) {
2558 flags |= REDIRECT_FLAG_APPEND_SLASH;
2559 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002560 else if (strcmp(args[cur_arg], "if") == 0 ||
2561 strcmp(args[cur_arg], "unless") == 0) {
2562 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2563 if (!cond) {
2564 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2565 file, linenum, args[0]);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002569 break;
2570 }
2571 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002572 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 +02002573 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002576 }
2577 cur_arg++;
2578 }
2579
2580 if (type == REDIRECT_TYPE_NONE) {
2581 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002585 }
2586
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2588 rule->cond = cond;
2589 rule->rdr_str = strdup(destination);
2590 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002591 if (cookie) {
2592 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002593 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 */
2595 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002596 if (cookie_set) {
2597 rule->cookie_str = malloc(rule->cookie_len + 10);
2598 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2599 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2600 rule->cookie_len += 9;
2601 } else {
2602 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002603 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002604 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2605 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 }
2607 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 rule->type = type;
2609 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002610 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002611 LIST_INIT(&rule->list);
2612 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002613 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2614 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002615 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002616 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002617 struct switching_rule *rule;
2618
Willy Tarreaub099aca2008-10-12 17:26:37 +02002619 if (curproxy == &defproxy) {
2620 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002623 }
2624
Willy Tarreau55ea7572007-06-17 19:56:27 +02002625 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627
2628 if (*(args[1]) == 0) {
2629 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002632 }
2633
Willy Tarreauef6494c2010-01-28 17:12:36 +01002634 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002635 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_ALERT | ERR_FATAL;
2638 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002639 }
2640
Willy Tarreauef6494c2010-01-28 17:12:36 +01002641 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002642 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002643 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002646 }
2647
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002648 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002649
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2651 rule->cond = cond;
2652 rule->be.name = strdup(args[1]);
2653 LIST_INIT(&rule->list);
2654 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2655 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002656 else if ((!strcmp(args[0], "force-persist")) ||
2657 (!strcmp(args[0], "ignore-persist"))) {
2658 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002659
2660 if (curproxy == &defproxy) {
2661 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
2666 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2667 err_code |= ERR_WARN;
2668
Willy Tarreauef6494c2010-01-28 17:12:36 +01002669 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002670 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2671 file, linenum, args[0]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
Willy Tarreauef6494c2010-01-28 17:12:36 +01002676 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002677 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2678 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002683 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002684
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002685 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002686 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002687 if (!strcmp(args[0], "force-persist")) {
2688 rule->type = PERSIST_TYPE_FORCE;
2689 } else {
2690 rule->type = PERSIST_TYPE_IGNORE;
2691 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002692 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002693 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002694 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002695 else if (!strcmp(args[0], "stick-table")) {
2696 int myidx = 1;
2697
Emeric Brun32da3c42010-09-23 18:39:19 +02002698 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002699 curproxy->table.type = (unsigned int)-1;
2700 while (*args[myidx]) {
2701 const char *err;
2702
2703 if (strcmp(args[myidx], "size") == 0) {
2704 myidx++;
2705 if (!*(args[myidx])) {
2706 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2707 file, linenum, args[myidx-1]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2712 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2713 file, linenum, *err, args[myidx-1]);
2714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
2716 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002717 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002718 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002719 else if (strcmp(args[myidx], "peers") == 0) {
2720 myidx++;
2721 if (!*(args[myidx])) {
2722 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2723 file, linenum, args[myidx-1]);
2724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
2726 }
2727 curproxy->table.peers.name = strdup(args[myidx++]);
2728 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 else if (strcmp(args[myidx], "expire") == 0) {
2730 myidx++;
2731 if (!*(args[myidx])) {
2732 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2733 file, linenum, args[myidx-1]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2738 if (err) {
2739 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2740 file, linenum, *err, args[myidx-1]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002745 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002746 }
2747 else if (strcmp(args[myidx], "nopurge") == 0) {
2748 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002749 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002750 }
2751 else if (strcmp(args[myidx], "type") == 0) {
2752 myidx++;
2753 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2754 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2755 file, linenum, args[myidx]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002759 /* myidx already points to next arg */
2760 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002761 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002762 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002763 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002764
2765 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002766 nw = args[myidx];
2767 while (*nw) {
2768 /* the "store" keyword supports a comma-separated list */
2769 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002770 sa = NULL; /* store arg */
2771 while (*nw && *nw != ',') {
2772 if (*nw == '(') {
2773 *nw = 0;
2774 sa = ++nw;
2775 while (*nw != ')') {
2776 if (!*nw) {
2777 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2778 file, linenum, args[0], cw);
2779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
2781 }
2782 nw++;
2783 }
2784 *nw = '\0';
2785 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002786 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002787 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002788 if (*nw)
2789 *nw++ = '\0';
2790 type = stktable_get_data_type(cw);
2791 if (type < 0) {
2792 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2793 file, linenum, args[0], cw);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
2796 }
Willy Tarreauac782882010-06-20 10:41:54 +02002797
2798 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2799 switch (err) {
2800 case PE_NONE: break;
2801 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002802 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2803 file, linenum, args[0], cw);
2804 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002805 break;
2806
2807 case PE_ARG_MISSING:
2808 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2809 file, linenum, args[0], cw);
2810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
2812
2813 case PE_ARG_NOT_USED:
2814 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2815 file, linenum, args[0], cw);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818
2819 default:
2820 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2821 file, linenum, args[0], cw);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002824 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002825 }
2826 myidx++;
2827 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002828 else {
2829 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2830 file, linenum, args[myidx]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002833 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002834 }
2835
2836 if (!curproxy->table.size) {
2837 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2838 file, linenum);
2839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
2841 }
2842
2843 if (curproxy->table.type == (unsigned int)-1) {
2844 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2845 file, linenum);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849 }
2850 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002851 struct sticking_rule *rule;
2852 struct pattern_expr *expr;
2853 int myidx = 0;
2854 const char *name = NULL;
2855 int flags;
2856
2857 if (curproxy == &defproxy) {
2858 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862
2863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2864 err_code |= ERR_WARN;
2865 goto out;
2866 }
2867
2868 myidx++;
2869 if ((strcmp(args[myidx], "store") == 0) ||
2870 (strcmp(args[myidx], "store-request") == 0)) {
2871 myidx++;
2872 flags = STK_IS_STORE;
2873 }
2874 else if (strcmp(args[myidx], "store-response") == 0) {
2875 myidx++;
2876 flags = STK_IS_STORE | STK_ON_RSP;
2877 }
2878 else if (strcmp(args[myidx], "match") == 0) {
2879 myidx++;
2880 flags = STK_IS_MATCH;
2881 }
2882 else if (strcmp(args[myidx], "on") == 0) {
2883 myidx++;
2884 flags = STK_IS_MATCH | STK_IS_STORE;
2885 }
2886 else {
2887 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891
2892 if (*(args[myidx]) == 0) {
2893 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
Emeric Brun485479d2010-09-23 18:02:19 +02002898 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002899 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002900 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
2904
2905 if (flags & STK_ON_RSP) {
2906 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2907 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2908 file, linenum, args[0], expr->fetch->kw);
2909 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002910 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 goto out;
2912 }
2913 } else {
2914 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2915 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2916 file, linenum, args[0], expr->fetch->kw);
2917 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002918 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002919 goto out;
2920 }
2921 }
2922
2923 if (strcmp(args[myidx], "table") == 0) {
2924 myidx++;
2925 name = args[myidx++];
2926 }
2927
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2929 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002930 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2931 file, linenum, args[0]);
2932 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002933 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 goto out;
2935 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002937 else if (*(args[myidx])) {
2938 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2939 file, linenum, args[0], args[myidx]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002941 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002942 goto out;
2943 }
Emeric Brun97679e72010-09-23 17:56:44 +02002944 if (flags & STK_ON_RSP)
2945 err_code |= warnif_cond_requires_req(cond, file, linenum);
2946 else
2947 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002948
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2950 rule->cond = cond;
2951 rule->expr = expr;
2952 rule->flags = flags;
2953 rule->table.name = name ? strdup(name) : NULL;
2954 LIST_INIT(&rule->list);
2955 if (flags & STK_ON_RSP)
2956 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2957 else
2958 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2959 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002962 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002963
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2965 curproxy->uri_auth = NULL; /* we must detach from the default config */
2966
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002967 if (!*args[1]) {
2968 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002969 } else if (!strcmp(args[1], "admin")) {
2970 struct stats_admin_rule *rule;
2971
2972 if (curproxy == &defproxy) {
2973 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
2976 }
2977
2978 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2979 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2980 err_code |= ERR_ALERT | ERR_ABORT;
2981 goto out;
2982 }
2983
2984 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2985 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2986 file, linenum, args[0], args[1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2991 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2992 file, linenum, args[0], args[1]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996
2997 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2998
2999 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3000 rule->cond = cond;
3001 LIST_INIT(&rule->list);
3002 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 } else if (!strcmp(args[1], "uri")) {
3004 if (*(args[2]) == 0) {
3005 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3009 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_ALERT | ERR_ABORT;
3011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 }
3013 } else if (!strcmp(args[1], "realm")) {
3014 if (*(args[2]) == 0) {
3015 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_ABORT;
3021 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003023 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003024 unsigned interval;
3025
3026 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3027 if (err) {
3028 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3029 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003032 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3033 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_ABORT;
3035 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003036 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003037 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003038 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003039
3040 if (curproxy == &defproxy) {
3041 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044 }
3045
3046 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3047 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
3050 }
3051
Willy Tarreauff011f22011-01-06 17:51:27 +01003052 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3053 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003054 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3055 file, linenum, args[0]);
3056 err_code |= ERR_WARN;
3057 }
3058
Willy Tarreauff011f22011-01-06 17:51:27 +01003059 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003060
Willy Tarreauff011f22011-01-06 17:51:27 +01003061 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003062 err_code |= ERR_ALERT | ERR_ABORT;
3063 goto out;
3064 }
3065
Willy Tarreauff011f22011-01-06 17:51:27 +01003066 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3067 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003068
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 } else if (!strcmp(args[1], "auth")) {
3070 if (*(args[2]) == 0) {
3071 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3075 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_ABORT;
3077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 }
3079 } else if (!strcmp(args[1], "scope")) {
3080 if (*(args[2]) == 0) {
3081 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3085 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003086 err_code |= ERR_ALERT | ERR_ABORT;
3087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 }
3089 } else if (!strcmp(args[1], "enable")) {
3090 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3091 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_ABORT;
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003095 } else if (!strcmp(args[1], "hide-version")) {
3096 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3097 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_ABORT;
3099 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003100 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003101 } else if (!strcmp(args[1], "show-legends")) {
3102 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3103 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3104 err_code |= ERR_ALERT | ERR_ABORT;
3105 goto out;
3106 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003107 } else if (!strcmp(args[1], "show-node")) {
3108
3109 if (*args[2]) {
3110 int i;
3111 char c;
3112
3113 for (i=0; args[2][i]; i++) {
3114 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003115 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3116 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003117 break;
3118 }
3119
3120 if (!i || args[2][i]) {
3121 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3122 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3123 file, linenum, args[0], args[1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127 }
3128
3129 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3130 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3131 err_code |= ERR_ALERT | ERR_ABORT;
3132 goto out;
3133 }
3134 } else if (!strcmp(args[1], "show-desc")) {
3135 char *desc = NULL;
3136
3137 if (*args[2]) {
3138 int i, len=0;
3139 char *d;
3140
3141 for(i=2; *args[i]; i++)
3142 len += strlen(args[i])+1;
3143
3144 desc = d = (char *)calloc(1, len);
3145
3146 d += sprintf(d, "%s", args[2]);
3147 for(i=3; *args[i]; i++)
3148 d += sprintf(d, " %s", args[i]);
3149 }
3150
3151 if (!*args[2] && !global.desc)
3152 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3153 file, linenum, args[1]);
3154 else {
3155 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3156 free(desc);
3157 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3158 err_code |= ERR_ALERT | ERR_ABORT;
3159 goto out;
3160 }
3161 free(desc);
3162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003164stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003165 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 +01003166 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
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 }
3170 }
3171 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003172 int optnum;
3173
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003174 if (*(args[1]) == '\0') {
3175 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3176 file, linenum, args[0]);
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 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003180
3181 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3182 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003183 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3184 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3185 file, linenum, cfg_opts[optnum].name);
3186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
3188 }
Willy Tarreau93893792009-07-23 13:19:11 +02003189 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3190 err_code |= ERR_WARN;
3191 goto out;
3192 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003193
Willy Tarreau3842f002009-06-14 11:39:52 +02003194 curproxy->no_options &= ~cfg_opts[optnum].val;
3195 curproxy->options &= ~cfg_opts[optnum].val;
3196
3197 switch (kwm) {
3198 case KWM_STD:
3199 curproxy->options |= cfg_opts[optnum].val;
3200 break;
3201 case KWM_NO:
3202 curproxy->no_options |= cfg_opts[optnum].val;
3203 break;
3204 case KWM_DEF: /* already cleared */
3205 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003206 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003207
Willy Tarreau93893792009-07-23 13:19:11 +02003208 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003209 }
3210 }
3211
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003212 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3213 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003214 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3215 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3216 file, linenum, cfg_opts2[optnum].name);
3217 err_code |= ERR_ALERT | ERR_FATAL;
3218 goto out;
3219 }
Willy Tarreau93893792009-07-23 13:19:11 +02003220 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3221 err_code |= ERR_WARN;
3222 goto out;
3223 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003224
Willy Tarreau3842f002009-06-14 11:39:52 +02003225 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3226 curproxy->options2 &= ~cfg_opts2[optnum].val;
3227
3228 switch (kwm) {
3229 case KWM_STD:
3230 curproxy->options2 |= cfg_opts2[optnum].val;
3231 break;
3232 case KWM_NO:
3233 curproxy->no_options2 |= cfg_opts2[optnum].val;
3234 break;
3235 case KWM_DEF: /* already cleared */
3236 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003237 }
Willy Tarreau93893792009-07-23 13:19:11 +02003238 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003239 }
3240 }
3241
Willy Tarreau3842f002009-06-14 11:39:52 +02003242 if (kwm != KWM_STD) {
3243 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003244 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003247 }
3248
Emeric Brun3a058f32009-06-30 18:26:00 +02003249 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003251 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003253 if (*(args[2]) != '\0') {
3254 if (!strcmp(args[2], "clf")) {
3255 curproxy->options2 |= PR_O2_CLFLOG;
3256 } else {
3257 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 }
3261 }
3262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 else if (!strcmp(args[1], "tcplog"))
3264 /* generate a detailed TCP log */
3265 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 else if (!strcmp(args[1], "tcpka")) {
3267 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003270
3271 if (curproxy->cap & PR_CAP_FE)
3272 curproxy->options |= PR_O_TCP_CLI_KA;
3273 if (curproxy->cap & PR_CAP_BE)
3274 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 }
3276 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_WARN;
3279
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003281 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003282 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003283 curproxy->options2 &= ~PR_O2_CHK_ANY;
3284 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285 if (!*args[2]) { /* no argument */
3286 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3287 curproxy->check_len = strlen(DEF_CHECK_REQ);
3288 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003289 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 curproxy->check_req = (char *)malloc(reqlen);
3291 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003292 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003294 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 if (*args[4])
3296 reqlen += strlen(args[4]);
3297 else
3298 reqlen += strlen("HTTP/1.0");
3299
3300 curproxy->check_req = (char *)malloc(reqlen);
3301 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003302 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003304 }
3305 else if (!strcmp(args[1], "ssl-hello-chk")) {
3306 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003309
Willy Tarreaua534fea2008-08-03 12:19:50 +02003310 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003311 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003312 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003313 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreau23677902007-05-08 23:50:35 +02003315 else if (!strcmp(args[1], "smtpchk")) {
3316 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003317 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003318 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003319 curproxy->options2 &= ~PR_O2_CHK_ANY;
3320 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003321
3322 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3323 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3324 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3325 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3326 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3327 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3328 curproxy->check_req = (char *)malloc(reqlen);
3329 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3330 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3331 } else {
3332 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3333 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3334 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3335 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3336 }
3337 }
3338 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003339 else if (!strcmp(args[1], "pgsql-check")) {
3340 /* use PostgreSQL request to check servers' health */
3341 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3342 err_code |= ERR_WARN;
3343
3344 free(curproxy->check_req);
3345 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003346 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003347 curproxy->options2 |= PR_O2_PGSQL_CHK;
3348
3349 if (*(args[2])) {
3350 int cur_arg = 2;
3351
3352 while (*(args[cur_arg])) {
3353 if (strcmp(args[cur_arg], "user") == 0) {
3354 char * packet;
3355 uint32_t packet_len;
3356 uint32_t pv;
3357
3358 /* suboption header - needs additional argument for it */
3359 if (*(args[cur_arg+1]) == 0) {
3360 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3361 file, linenum, args[0], args[1], args[cur_arg]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365
3366 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3367 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3368 pv = htonl(0x30000); /* protocol version 3.0 */
3369
3370 packet = (char*) calloc(1, packet_len);
3371
3372 memcpy(packet + 4, &pv, 4);
3373
3374 /* copy "user" */
3375 memcpy(packet + 8, "user", 4);
3376
3377 /* copy username */
3378 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3379
3380 free(curproxy->check_req);
3381 curproxy->check_req = packet;
3382 curproxy->check_len = packet_len;
3383
3384 packet_len = htonl(packet_len);
3385 memcpy(packet, &packet_len, 4);
3386 cur_arg += 2;
3387 } else {
3388 /* unknown suboption - catchall */
3389 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3390 file, linenum, args[0], args[1]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394 } /* end while loop */
3395 }
3396 }
3397
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003398 else if (!strcmp(args[1], "redis-check")) {
3399 /* use REDIS PING request to check servers' health */
3400 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3401 err_code |= ERR_WARN;
3402
3403 free(curproxy->check_req);
3404 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003405 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003406 curproxy->options2 |= PR_O2_REDIS_CHK;
3407
3408 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3409 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3410 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3411 }
3412
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003413 else if (!strcmp(args[1], "mysql-check")) {
3414 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3416 err_code |= ERR_WARN;
3417
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003418 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003422
3423 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3424 * const char mysql40_client_auth_pkt[] = {
3425 * "\x0e\x00\x00" // packet length
3426 * "\x01" // packet number
3427 * "\x00\x00" // client capabilities
3428 * "\x00\x00\x01" // max packet
3429 * "haproxy\x00" // username (null terminated string)
3430 * "\x00" // filler (always 0x00)
3431 * "\x01\x00\x00" // packet length
3432 * "\x00" // packet number
3433 * "\x01" // COM_QUIT command
3434 * };
3435 */
3436
3437 if (*(args[2])) {
3438 int cur_arg = 2;
3439
3440 while (*(args[cur_arg])) {
3441 if (strcmp(args[cur_arg], "user") == 0) {
3442 char *mysqluser;
3443 int packetlen, reqlen, userlen;
3444
3445 /* suboption header - needs additional argument for it */
3446 if (*(args[cur_arg+1]) == 0) {
3447 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3448 file, linenum, args[0], args[1], args[cur_arg]);
3449 err_code |= ERR_ALERT | ERR_FATAL;
3450 goto out;
3451 }
3452 mysqluser = args[cur_arg + 1];
3453 userlen = strlen(mysqluser);
3454 packetlen = userlen + 7;
3455 reqlen = packetlen + 9;
3456
3457 free(curproxy->check_req);
3458 curproxy->check_req = (char *)calloc(1, reqlen);
3459 curproxy->check_len = reqlen;
3460
3461 snprintf(curproxy->check_req, 4, "%c%c%c",
3462 ((unsigned char) packetlen & 0xff),
3463 ((unsigned char) (packetlen >> 8) & 0xff),
3464 ((unsigned char) (packetlen >> 16) & 0xff));
3465
3466 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003467 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003468 curproxy->check_req[8] = 1;
3469 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3470 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3471 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3472 cur_arg += 2;
3473 } else {
3474 /* unknown suboption - catchall */
3475 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3476 file, linenum, args[0], args[1]);
3477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480 } /* end while loop */
3481 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003482 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003483 else if (!strcmp(args[1], "ldap-check")) {
3484 /* use LDAP request to check servers' health */
3485 free(curproxy->check_req);
3486 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003487 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003488 curproxy->options2 |= PR_O2_LDAP_CHK;
3489
3490 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3491 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3492 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3493 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003494 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003495 int cur_arg;
3496
3497 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3498 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003499 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003500
Willy Tarreau87cf5142011-08-19 22:57:24 +02003501 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003502
3503 free(curproxy->fwdfor_hdr_name);
3504 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3505 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3506
3507 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3508 cur_arg = 2;
3509 while (*(args[cur_arg])) {
3510 if (!strcmp(args[cur_arg], "except")) {
3511 /* suboption except - needs additional argument for it */
3512 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3513 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3514 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003515 err_code |= ERR_ALERT | ERR_FATAL;
3516 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003517 }
3518 /* flush useless bits */
3519 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003520 cur_arg += 2;
3521 } else if (!strcmp(args[cur_arg], "header")) {
3522 /* suboption header - needs additional argument for it */
3523 if (*(args[cur_arg+1]) == 0) {
3524 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003526 err_code |= ERR_ALERT | ERR_FATAL;
3527 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003528 }
3529 free(curproxy->fwdfor_hdr_name);
3530 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3531 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3532 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003533 } else if (!strcmp(args[cur_arg], "if-none")) {
3534 curproxy->options &= ~PR_O_FF_ALWAYS;
3535 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003536 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003538 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003539 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003542 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003544 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003545 else if (!strcmp(args[1], "originalto")) {
3546 int cur_arg;
3547
3548 /* insert x-original-to field, but not for the IP address listed as an except.
3549 * set default options (ie: bitfield, header name, etc)
3550 */
3551
3552 curproxy->options |= PR_O_ORGTO;
3553
3554 free(curproxy->orgto_hdr_name);
3555 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3556 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3557
Willy Tarreau87cf5142011-08-19 22:57:24 +02003558 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003559 cur_arg = 2;
3560 while (*(args[cur_arg])) {
3561 if (!strcmp(args[cur_arg], "except")) {
3562 /* suboption except - needs additional argument for it */
3563 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3564 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3565 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003568 }
3569 /* flush useless bits */
3570 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3571 cur_arg += 2;
3572 } else if (!strcmp(args[cur_arg], "header")) {
3573 /* suboption header - needs additional argument for it */
3574 if (*(args[cur_arg+1]) == 0) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003579 }
3580 free(curproxy->orgto_hdr_name);
3581 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3582 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3583 cur_arg += 2;
3584 } else {
3585 /* unknown suboption - catchall */
3586 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3587 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003590 }
3591 } /* end while loop */
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else {
3594 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
Willy Tarreau93893792009-07-23 13:19:11 +02003598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003600 else if (!strcmp(args[0], "default_backend")) {
3601 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003603
3604 if (*(args[1]) == 0) {
3605 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003608 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003609 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003610 curproxy->defbe.name = strdup(args[1]);
3611 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003613 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003615
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003616 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3617 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003619 /* enable reconnections to dispatch */
3620 curproxy->options |= PR_O_REDISP;
3621 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003622 else if (!strcmp(args[0], "http-check")) {
3623 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003625
3626 if (strcmp(args[1], "disable-on-404") == 0) {
3627 /* enable a graceful server shutdown on an HTTP 404 response */
3628 curproxy->options |= PR_O_DISABLE404;
3629 }
Willy Tarreauef781042010-01-27 11:53:01 +01003630 else if (strcmp(args[1], "send-state") == 0) {
3631 /* enable emission of the apparent state of a server in HTTP checks */
3632 curproxy->options2 |= PR_O2_CHK_SNDST;
3633 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003634 else if (strcmp(args[1], "expect") == 0) {
3635 const char *ptr_arg;
3636 int cur_arg;
3637
3638 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3639 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
3642 }
3643
3644 cur_arg = 2;
3645 /* consider exclamation marks, sole or at the beginning of a word */
3646 while (*(ptr_arg = args[cur_arg])) {
3647 while (*ptr_arg == '!') {
3648 curproxy->options2 ^= PR_O2_EXP_INV;
3649 ptr_arg++;
3650 }
3651 if (*ptr_arg)
3652 break;
3653 cur_arg++;
3654 }
3655 /* now ptr_arg points to the beginning of a word past any possible
3656 * exclamation mark, and cur_arg is the argument which holds this word.
3657 */
3658 if (strcmp(ptr_arg, "status") == 0) {
3659 if (!*(args[cur_arg + 1])) {
3660 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3661 file, linenum, args[0], args[1], ptr_arg);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003666 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003667 curproxy->expect_str = strdup(args[cur_arg + 1]);
3668 }
3669 else if (strcmp(ptr_arg, "string") == 0) {
3670 if (!*(args[cur_arg + 1])) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3672 file, linenum, args[0], args[1], ptr_arg);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003677 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003678 curproxy->expect_str = strdup(args[cur_arg + 1]);
3679 }
3680 else if (strcmp(ptr_arg, "rstatus") == 0) {
3681 if (!*(args[cur_arg + 1])) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3683 file, linenum, args[0], args[1], ptr_arg);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
3687 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003688 free(curproxy->expect_str);
3689 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3690 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003691 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3692 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3693 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3694 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 }
3699 else if (strcmp(ptr_arg, "rstring") == 0) {
3700 if (!*(args[cur_arg + 1])) {
3701 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3702 file, linenum, args[0], args[1], ptr_arg);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003707 free(curproxy->expect_str);
3708 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3709 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003710 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3711 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3712 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3713 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 }
3718 else {
3719 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3720 file, linenum, args[0], args[1], ptr_arg);
3721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
3723 }
3724 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003725 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003726 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 +02003727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003729 }
3730 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003731 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003732 if (curproxy == &defproxy) {
3733 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003736 }
3737
Willy Tarreaub80c2302007-11-30 20:51:32 +01003738 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740
3741 if (strcmp(args[1], "fail") == 0) {
3742 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003743 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003744 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3745 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 }
3749
Willy Tarreauef6494c2010-01-28 17:12:36 +01003750 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003751 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3752 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003755 }
3756 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3757 }
3758 else {
3759 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003762 }
3763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764#ifdef TPROXY
3765 else if (!strcmp(args[0], "transparent")) {
3766 /* enable transparent proxy connections */
3767 curproxy->options |= PR_O_TRANSP;
3768 }
3769#endif
3770 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003773
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 if (*(args[1]) == 0) {
3775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 }
3779 curproxy->maxconn = atol(args[1]);
3780 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003781 else if (!strcmp(args[0], "backlog")) { /* backlog */
3782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003783 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003784
3785 if (*(args[1]) == 0) {
3786 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003789 }
3790 curproxy->backlog = atol(args[1]);
3791 }
Willy Tarreau86034312006-12-29 00:10:33 +01003792 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003795
Willy Tarreau86034312006-12-29 00:10:33 +01003796 if (*(args[1]) == 0) {
3797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003800 }
3801 curproxy->fullconn = atol(args[1]);
3802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3804 if (*(args[1]) == 0) {
3805 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003809 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3810 if (err) {
3811 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3812 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003815 }
3816 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003819 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003825 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003827
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 if (strchr(args[1], ':') == NULL) {
3829 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003833 sk = str2sa(args[1]);
3834 if (!sk) {
3835 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
3838 }
3839 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003840 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003845
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003846 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003847 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3848 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003853 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3855 err_code |= ERR_WARN;
3856
3857 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3858 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3859 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3860 }
3861 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3862 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3863 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3864 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003865 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3866 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3867 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3868 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003869 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003870 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
3873 }
3874 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003875 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003877 char *rport, *raddr;
3878 short realport = 0;
3879 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003881 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003886 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888
3889 if (!*args[2]) {
3890 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3891 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003895
3896 err = invalid_char(args[1]);
3897 if (err) {
3898 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3899 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003902 }
3903
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003904 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003905 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003906
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003907 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3908 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3909 err_code |= ERR_ALERT | ERR_ABORT;
3910 goto out;
3911 }
3912
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003913 /* the servers are linked backwards first */
3914 newsrv->next = curproxy->srv;
3915 curproxy->srv = newsrv;
3916 newsrv->proxy = curproxy;
3917 newsrv->conf.file = file;
3918 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919
Simon Hormanaf514952011-06-21 14:34:57 +09003920 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003921 LIST_INIT(&newsrv->pendconns);
3922 do_check = 0;
3923 newsrv->state = SRV_RUNNING; /* early server setup */
3924 newsrv->last_change = now.tv_sec;
3925 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003927 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003928 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 * - IP: => port=+0, relative
3930 * - IP:N => port=N, absolute
3931 * - IP:+N => port=+N, relative
3932 * - IP:-N => port=-N, relative
3933 */
3934 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003935 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 if (rport) {
3937 *rport++ = 0;
3938 realport = atol(rport);
3939 if (!isdigit((unsigned char)*rport))
3940 newsrv->state |= SRV_MAPPORTS;
3941 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003943
Willy Tarreaufab5a432011-03-04 15:31:53 +01003944 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003946 if (!sk) {
3947 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003952 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003953
3954 newsrv->check_port = curproxy->defsrv.check_port;
3955 newsrv->inter = curproxy->defsrv.inter;
3956 newsrv->fastinter = curproxy->defsrv.fastinter;
3957 newsrv->downinter = curproxy->defsrv.downinter;
3958 newsrv->rise = curproxy->defsrv.rise;
3959 newsrv->fall = curproxy->defsrv.fall;
3960 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3961 newsrv->minconn = curproxy->defsrv.minconn;
3962 newsrv->maxconn = curproxy->defsrv.maxconn;
3963 newsrv->slowstart = curproxy->defsrv.slowstart;
3964 newsrv->onerror = curproxy->defsrv.onerror;
3965 newsrv->consecutive_errors_limit
3966 = curproxy->defsrv.consecutive_errors_limit;
3967 newsrv->uweight = newsrv->iweight
3968 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003970 newsrv->curfd = -1; /* no health-check in progress */
3971 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003973 cur_arg = 3;
3974 } else {
3975 newsrv = &curproxy->defsrv;
3976 cur_arg = 1;
3977 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003978
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003981 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003982
3983 if (!*args[cur_arg + 1]) {
3984 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3985 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003988 }
3989
3990 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003991 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003992
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003993 if (newsrv->puid <= 0) {
3994 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003995 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003998 }
3999
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004000 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4001 if (node) {
4002 struct server *target = container_of(node, struct server, conf.id);
4003 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4004 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004009 cur_arg += 2;
4010 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004011 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 newsrv->cookie = strdup(args[cur_arg + 1]);
4013 newsrv->cklen = strlen(args[cur_arg + 1]);
4014 cur_arg += 2;
4015 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004016 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004017 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4018 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4019 cur_arg += 2;
4020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004022 if (!*args[cur_arg + 1]) {
4023 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4024 file, linenum, args[cur_arg]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004030 if (newsrv->rise <= 0) {
4031 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4032 file, linenum, args[cur_arg]);
4033 err_code |= ERR_ALERT | ERR_FATAL;
4034 goto out;
4035 }
4036
Willy Tarreau96839092010-03-29 10:02:24 +02004037 if (newsrv->health)
4038 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 cur_arg += 2;
4040 }
4041 else if (!strcmp(args[cur_arg], "fall")) {
4042 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004043
4044 if (!*args[cur_arg + 1]) {
4045 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4046 file, linenum, args[cur_arg]);
4047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
4049 }
4050
4051 if (newsrv->fall <= 0) {
4052 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4053 file, linenum, args[cur_arg]);
4054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
4056 }
4057
Willy Tarreaubaaee002006-06-26 02:48:02 +02004058 cur_arg += 2;
4059 }
4060 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004061 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4062 if (err) {
4063 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4064 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004067 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004068 if (val <= 0) {
4069 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4070 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004073 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004074 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 cur_arg += 2;
4076 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004077 else if (!strcmp(args[cur_arg], "fastinter")) {
4078 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4079 if (err) {
4080 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4081 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004084 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004085 if (val <= 0) {
4086 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4087 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004090 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004091 newsrv->fastinter = val;
4092 cur_arg += 2;
4093 }
4094 else if (!strcmp(args[cur_arg], "downinter")) {
4095 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4096 if (err) {
4097 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4098 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004101 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004102 if (val <= 0) {
4103 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4104 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004107 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004108 newsrv->downinter = val;
4109 cur_arg += 2;
4110 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004111 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004112 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004113 if (!sk) {
4114 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004119 cur_arg += 2;
4120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 else if (!strcmp(args[cur_arg], "port")) {
4122 newsrv->check_port = atol(args[cur_arg + 1]);
4123 cur_arg += 2;
4124 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004125 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004126 newsrv->state |= SRV_BACKUP;
4127 cur_arg ++;
4128 }
Simon Hormanfa461682011-06-25 09:39:49 +09004129 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4130 newsrv->state |= SRV_NON_STICK;
4131 cur_arg ++;
4132 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004133 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4134 newsrv->state |= SRV_SEND_PROXY;
4135 cur_arg ++;
4136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 else if (!strcmp(args[cur_arg], "weight")) {
4138 int w;
4139 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004140 if (w < 0 || w > 256) {
4141 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004143 err_code |= ERR_ALERT | ERR_FATAL;
4144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004146 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004147 cur_arg += 2;
4148 }
4149 else if (!strcmp(args[cur_arg], "minconn")) {
4150 newsrv->minconn = atol(args[cur_arg + 1]);
4151 cur_arg += 2;
4152 }
4153 else if (!strcmp(args[cur_arg], "maxconn")) {
4154 newsrv->maxconn = atol(args[cur_arg + 1]);
4155 cur_arg += 2;
4156 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004157 else if (!strcmp(args[cur_arg], "maxqueue")) {
4158 newsrv->maxqueue = atol(args[cur_arg + 1]);
4159 cur_arg += 2;
4160 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004161 else if (!strcmp(args[cur_arg], "slowstart")) {
4162 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004163 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004164 if (err) {
4165 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4166 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004169 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004170 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004171 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4172 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004175 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004176 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004177 cur_arg += 2;
4178 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004179 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004180
4181 if (!*args[cur_arg + 1]) {
4182 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4183 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004186 }
4187
4188 newsrv->trackit = strdup(args[cur_arg + 1]);
4189
4190 cur_arg += 2;
4191 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004192 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 global.maxsock++;
4194 do_check = 1;
4195 cur_arg += 1;
4196 }
Willy Tarreau96839092010-03-29 10:02:24 +02004197 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4198 newsrv->state |= SRV_MAINTAIN;
4199 newsrv->state &= ~SRV_RUNNING;
4200 newsrv->health = 0;
4201 cur_arg += 1;
4202 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004203 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004204 if (!strcmp(args[cur_arg + 1], "none"))
4205 newsrv->observe = HANA_OBS_NONE;
4206 else if (!strcmp(args[cur_arg + 1], "layer4"))
4207 newsrv->observe = HANA_OBS_LAYER4;
4208 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4209 if (curproxy->mode != PR_MODE_HTTP) {
4210 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4211 file, linenum, args[cur_arg + 1]);
4212 err_code |= ERR_ALERT;
4213 }
4214 newsrv->observe = HANA_OBS_LAYER7;
4215 }
4216 else {
4217 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004218 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004219 file, linenum, args[cur_arg], args[cur_arg + 1]);
4220 err_code |= ERR_ALERT | ERR_FATAL;
4221 goto out;
4222 }
4223
4224 cur_arg += 2;
4225 }
4226 else if (!strcmp(args[cur_arg], "on-error")) {
4227 if (!strcmp(args[cur_arg + 1], "fastinter"))
4228 newsrv->onerror = HANA_ONERR_FASTINTER;
4229 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4230 newsrv->onerror = HANA_ONERR_FAILCHK;
4231 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4232 newsrv->onerror = HANA_ONERR_SUDDTH;
4233 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4234 newsrv->onerror = HANA_ONERR_MARKDWN;
4235 else {
4236 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004237 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004238 file, linenum, args[cur_arg], args[cur_arg + 1]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242
4243 cur_arg += 2;
4244 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004245 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4246 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4247 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4248 else {
4249 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4250 file, linenum, args[cur_arg], args[cur_arg + 1]);
4251 err_code |= ERR_ALERT | ERR_FATAL;
4252 goto out;
4253 }
4254
4255 cur_arg += 2;
4256 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004257 else if (!strcmp(args[cur_arg], "error-limit")) {
4258 if (!*args[cur_arg + 1]) {
4259 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4260 file, linenum, args[cur_arg]);
4261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
4264
4265 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4266
4267 if (newsrv->consecutive_errors_limit <= 0) {
4268 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4269 file, linenum, args[cur_arg]);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004273 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004274 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004275 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004276 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004277 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004278
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004280#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004281 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004282 file, linenum, "source", "usesrc");
4283#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004284 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004286#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004289 }
4290 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004291 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4292 if (!sk) {
4293 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
4296 }
4297 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004298
4299 if (port_low != port_high) {
4300 int i;
4301 if (port_low <= 0 || port_low > 65535 ||
4302 port_high <= 0 || port_high > 65535 ||
4303 port_low > port_high) {
4304 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4305 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004308 }
4309 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4310 for (i = 0; i < newsrv->sport_range->size; i++)
4311 newsrv->sport_range->ports[i] = port_low + i;
4312 }
4313
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004315 while (*(args[cur_arg])) {
4316 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004317#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4318#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004319 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4320 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4321 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004324 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004325#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004326 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004327 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004331 }
4332 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004333 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004334 newsrv->state |= SRV_TPROXY_CLI;
4335 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004336 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004338 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4339 char *name, *end;
4340
4341 name = args[cur_arg+1] + 7;
4342 while (isspace(*name))
4343 name++;
4344
4345 end = name;
4346 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4347 end++;
4348
4349 newsrv->state &= ~SRV_TPROXY_MASK;
4350 newsrv->state |= SRV_TPROXY_DYN;
4351 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4352 newsrv->bind_hdr_len = end - name;
4353 memcpy(newsrv->bind_hdr_name, name, end - name);
4354 newsrv->bind_hdr_name[end-name] = '\0';
4355 newsrv->bind_hdr_occ = -1;
4356
4357 /* now look for an occurrence number */
4358 while (isspace(*end))
4359 end++;
4360 if (*end == ',') {
4361 end++;
4362 name = end;
4363 if (*end == '-')
4364 end++;
4365 while (isdigit(*end))
4366 end++;
4367 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4368 }
4369
4370 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4371 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4372 " occurrences values smaller than %d.\n",
4373 file, linenum, MAX_HDR_HISTORY);
4374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
4376 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004377 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004378 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004379 if (!sk) {
4380 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
4383 }
4384 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 }
4387 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004388#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004390#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 cur_arg += 2;
4392 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004393#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004395 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4399 } /* "usesrc" */
4400
4401 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4402#ifdef SO_BINDTODEVICE
4403 if (!*args[cur_arg + 1]) {
4404 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4405 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004408 }
4409 if (newsrv->iface_name)
4410 free(newsrv->iface_name);
4411
4412 newsrv->iface_name = strdup(args[cur_arg + 1]);
4413 newsrv->iface_len = strlen(newsrv->iface_name);
4414 global.last_checks |= LSTCHK_NETADM;
4415#else
4416 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4417 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004420#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004421 cur_arg += 2;
4422 continue;
4423 }
4424 /* this keyword in not an option of "source" */
4425 break;
4426 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004428 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004429 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4430 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004435 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004436 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 +01004437 file, linenum, newsrv->id);
4438 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004439 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 +01004440 file, linenum);
4441
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 }
4445 }
4446
4447 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004448 if (newsrv->trackit) {
4449 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4450 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004453 }
4454
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004455 /* try to get the port from check_addr if check_port not set */
4456 if (!newsrv->check_port)
4457 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004458
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4460 newsrv->check_port = realport; /* by default */
4461 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004462 /* not yet valid, because no port was set on
4463 * the server either. We'll check if we have
4464 * a known port on the first listener.
4465 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004466 struct listener *l = curproxy->listen;
4467 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4468 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004469 }
4470 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4472 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004476
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004477 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004478 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004479 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4480 err_code |= ERR_ALERT | ERR_ABORT;
4481 goto out;
4482 }
4483
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004484 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 newsrv->state |= SRV_CHECKED;
4486 }
4487
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004488 if (!defsrv) {
4489 if (newsrv->state & SRV_BACKUP)
4490 curproxy->srv_bck++;
4491 else
4492 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004493
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004494 newsrv->prev_state = newsrv->state;
4495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 }
4497 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004498 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 int facility;
4500
4501 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4502 curproxy->logfac1 = global.logfac1;
4503 curproxy->logsrv1 = global.logsrv1;
4504 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004505 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 curproxy->logfac2 = global.logfac2;
4507 curproxy->logsrv2 = global.logsrv2;
4508 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004509 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
4511 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004512 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513
4514 facility = get_log_facility(args[2]);
4515 if (facility < 0) {
4516 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4517 exit(1);
4518 }
4519
4520 level = 7; /* max syslog level = debug */
4521 if (*(args[3])) {
4522 level = get_log_level(args[3]);
4523 if (level < 0) {
4524 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4525 exit(1);
4526 }
4527 }
4528
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004529 minlvl = 0; /* limit syslog level to this level (emerg) */
4530 if (*(args[4])) {
4531 minlvl = get_log_level(args[4]);
4532 if (level < 0) {
4533 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4534 exit(1);
4535 }
4536 }
4537
Robert Tsai81ae1952007-12-05 10:47:29 +01004538 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004539 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004540 if (!sk) {
4541 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004542 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
4545 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004546 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004547 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004548 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004549 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004550 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004554 logsrv.addr = *sk;
4555 if (!get_host_port(&logsrv.addr))
4556 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558
4559 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004560 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 curproxy->logfac1 = facility;
4562 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004563 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 }
4565 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567 curproxy->logfac2 = facility;
4568 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004569 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 }
4571 else {
4572 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 }
4576 }
4577 else {
4578 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004585 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004586 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004587
Willy Tarreau977b8e42006-12-29 14:19:17 +01004588 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004590
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004592 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4593 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004597
4598 /* we must first clear any optional default setting */
4599 curproxy->options &= ~PR_O_TPXY_MASK;
4600 free(curproxy->iface_name);
4601 curproxy->iface_name = NULL;
4602 curproxy->iface_len = 0;
4603
Willy Tarreaud5191e72010-02-09 20:50:45 +01004604 sk = str2sa(args[1]);
4605 if (!sk) {
4606 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609 }
4610 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004612
4613 cur_arg = 2;
4614 while (*(args[cur_arg])) {
4615 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004616#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4617#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004618 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4619 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4620 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004623 }
4624#endif
4625 if (!*args[cur_arg + 1]) {
4626 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4627 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630 }
4631
4632 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004633 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004634 curproxy->options |= PR_O_TPXY_CLI;
4635 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004636 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004638 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4639 char *name, *end;
4640
4641 name = args[cur_arg+1] + 7;
4642 while (isspace(*name))
4643 name++;
4644
4645 end = name;
4646 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4647 end++;
4648
4649 curproxy->options &= ~PR_O_TPXY_MASK;
4650 curproxy->options |= PR_O_TPXY_DYN;
4651 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4652 curproxy->bind_hdr_len = end - name;
4653 memcpy(curproxy->bind_hdr_name, name, end - name);
4654 curproxy->bind_hdr_name[end-name] = '\0';
4655 curproxy->bind_hdr_occ = -1;
4656
4657 /* now look for an occurrence number */
4658 while (isspace(*end))
4659 end++;
4660 if (*end == ',') {
4661 end++;
4662 name = end;
4663 if (*end == '-')
4664 end++;
4665 while (isdigit(*end))
4666 end++;
4667 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4668 }
4669
4670 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4671 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4672 " occurrences values smaller than %d.\n",
4673 file, linenum, MAX_HDR_HISTORY);
4674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004677 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004678 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004679 if (!sk) {
4680 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
4684 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004685 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004686 }
4687 global.last_checks |= LSTCHK_NETADM;
4688#if !defined(CONFIG_HAP_LINUX_TPROXY)
4689 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004690#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004691#else /* no TPROXY support */
4692 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004693 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004694 err_code |= ERR_ALERT | ERR_FATAL;
4695 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004696#endif
4697 cur_arg += 2;
4698 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004699 }
4700
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004701 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4702#ifdef SO_BINDTODEVICE
4703 if (!*args[cur_arg + 1]) {
4704 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4705 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004708 }
4709 if (curproxy->iface_name)
4710 free(curproxy->iface_name);
4711
4712 curproxy->iface_name = strdup(args[cur_arg + 1]);
4713 curproxy->iface_len = strlen(curproxy->iface_name);
4714 global.last_checks |= LSTCHK_NETADM;
4715#else
4716 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4717 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004720#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004721 cur_arg += 2;
4722 continue;
4723 }
4724 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4725 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004730 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4731 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4732 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004737 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004743
4744 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4745 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004746 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004747 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
4750 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4752 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004753 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004754 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004758 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4759 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004760 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004761 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4766 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004767 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004768 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
4771 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4773 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004774 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004778 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4780 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004783 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004784 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004785 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4787 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004788 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004790 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004791 }
4792 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4794 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004795 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004797 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4802 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004805 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806
4807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4808 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004809 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 }
4813 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4815 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004816 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
4820 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004823 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4829 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004830 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 }
4834 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4836 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004837 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004841 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004846 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004847 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004849 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004850
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 if (curproxy == &defproxy) {
4852 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004856 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 if (*(args[1]) == 0) {
4860 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004864
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004865 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4866 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4867 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4868 file, linenum, args[0]);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4873 }
4874 else if (*args[2]) {
4875 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4876 file, linenum, args[0], args[2]);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004881 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004882 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004883 wl->s = strdup(args[1]);
4884 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004885 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
4887 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004888 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004894
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4896 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004897 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004898 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4903 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004904 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4910 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004911 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4918 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4924 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004925 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4931 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004932 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
4936 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4938 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004939 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
4943 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004944 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004945
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 if (curproxy == &defproxy) {
4947 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004951 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 if (*(args[1]) == 0) {
4955 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004960 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4962 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4963 file, linenum, args[0]);
4964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
4966 }
4967 err_code |= warnif_cond_requires_req(cond, file, linenum);
4968 }
4969 else if (*args[2]) {
4970 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4971 file, linenum, args[0], args[2]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004976 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004977 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004978 wl->s = strdup(args[1]);
4979 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981 else if (!strcmp(args[0], "errorloc") ||
4982 !strcmp(args[0], "errorloc302") ||
4983 !strcmp(args[0], "errorloc303")) { /* error location */
4984 int errnum, errlen;
4985 char *err;
4986
Willy Tarreau977b8e42006-12-29 14:19:17 +01004987 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004989
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004991 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", 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 }
4995
4996 errnum = atol(args[1]);
4997 if (!strcmp(args[0], "errorloc303")) {
4998 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4999 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5000 } else {
5001 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5002 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5003 }
5004
Willy Tarreau0f772532006-12-23 20:51:41 +01005005 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5006 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005007 chunk_destroy(&curproxy->errmsg[rc]);
5008 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005009 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005012
5013 if (rc >= HTTP_ERR_SIZE) {
5014 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5015 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 free(err);
5017 }
5018 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005019 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5020 int errnum, errlen, fd;
5021 char *err;
5022 struct stat stat;
5023
5024 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005025 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005026
5027 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005028 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005031 }
5032
5033 fd = open(args[2], O_RDONLY);
5034 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5035 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5036 file, linenum, args[2], args[1]);
5037 if (fd >= 0)
5038 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005041 }
5042
Willy Tarreau27a674e2009-08-17 07:23:33 +02005043 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005044 errlen = stat.st_size;
5045 } else {
5046 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005047 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005049 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005050 }
5051
5052 err = malloc(errlen); /* malloc() must succeed during parsing */
5053 errnum = read(fd, err, errlen);
5054 if (errnum != errlen) {
5055 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5056 file, linenum, args[2], args[1]);
5057 close(fd);
5058 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005061 }
5062 close(fd);
5063
5064 errnum = atol(args[1]);
5065 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5066 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005067 chunk_destroy(&curproxy->errmsg[rc]);
5068 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069 break;
5070 }
5071 }
5072
5073 if (rc >= HTTP_ERR_SIZE) {
5074 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5075 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005077 free(err);
5078 }
5079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005081 struct cfg_kw_list *kwl;
5082 int index;
5083
5084 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5085 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5086 if (kwl->kw[index].section != CFG_LISTEN)
5087 continue;
5088 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5089 /* prepare error message just in case */
5090 snprintf(trash, sizeof(trash),
5091 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005092 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5093 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005094 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005097 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005098 else if (rc > 0) {
5099 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_WARN;
5101 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005102 }
Willy Tarreau93893792009-07-23 13:19:11 +02005103 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005104 }
5105 }
5106 }
5107
Willy Tarreau6daf3432008-01-22 16:44:08 +01005108 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
Willy Tarreau93893792009-07-23 13:19:11 +02005112 out:
5113 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005114}
5115
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005116int
5117cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5118{
5119
5120 int err_code = 0;
5121 const char *err;
5122
5123 if (!strcmp(args[0], "userlist")) { /* new userlist */
5124 struct userlist *newul;
5125
5126 if (!*args[1]) {
5127 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5128 file, linenum, args[0]);
5129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
5131 }
5132
5133 err = invalid_char(args[1]);
5134 if (err) {
5135 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5136 file, linenum, *err, args[0], args[1]);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140
5141 for (newul = userlist; newul; newul = newul->next)
5142 if (!strcmp(newul->name, args[1])) {
5143 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5144 file, linenum, args[1]);
5145 err_code |= ERR_WARN;
5146 goto out;
5147 }
5148
5149 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5150 if (!newul) {
5151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5152 err_code |= ERR_ALERT | ERR_ABORT;
5153 goto out;
5154 }
5155
5156 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5157 newul->name = strdup(args[1]);
5158
5159 if (!newul->groupusers | !newul->name) {
5160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5161 err_code |= ERR_ALERT | ERR_ABORT;
5162 goto out;
5163 }
5164
5165 newul->next = userlist;
5166 userlist = newul;
5167
5168 } else if (!strcmp(args[0], "group")) { /* new group */
5169 int cur_arg, i;
5170 const char *err;
5171
5172 if (!*args[1]) {
5173 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5174 file, linenum, args[0]);
5175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
5178
5179 err = invalid_char(args[1]);
5180 if (err) {
5181 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5182 file, linenum, *err, args[0], args[1]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186
5187 for(i = 0; i < userlist->grpcnt; i++)
5188 if (!strcmp(userlist->groups[i], args[1])) {
5189 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5190 file, linenum, args[1], userlist->name);
5191 err_code |= ERR_ALERT;
5192 goto out;
5193 }
5194
5195 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5196 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5197 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
5201
5202 cur_arg = 2;
5203
5204 while (*args[cur_arg]) {
5205 if (!strcmp(args[cur_arg], "users")) {
5206 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5207 cur_arg += 2;
5208 continue;
5209 } else {
5210 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5211 file, linenum, args[0]);
5212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215 }
5216
5217 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5218 } else if (!strcmp(args[0], "user")) { /* new user */
5219 struct auth_users *newuser;
5220 int cur_arg;
5221
5222 if (!*args[1]) {
5223 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5224 file, linenum, args[0]);
5225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227 }
5228
5229 for (newuser = userlist->users; newuser; newuser = newuser->next)
5230 if (!strcmp(newuser->user, args[1])) {
5231 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5232 file, linenum, args[1], userlist->name);
5233 err_code |= ERR_ALERT;
5234 goto out;
5235 }
5236
5237 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5238 if (!newuser) {
5239 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5240 err_code |= ERR_ALERT | ERR_ABORT;
5241 goto out;
5242 }
5243
5244 newuser->user = strdup(args[1]);
5245
5246 newuser->next = userlist->users;
5247 userlist->users = newuser;
5248
5249 cur_arg = 2;
5250
5251 while (*args[cur_arg]) {
5252 if (!strcmp(args[cur_arg], "password")) {
5253#ifndef CONFIG_HAP_CRYPT
5254 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5255 file, linenum);
5256 err_code |= ERR_ALERT;
5257#endif
5258 newuser->pass = strdup(args[cur_arg + 1]);
5259 cur_arg += 2;
5260 continue;
5261 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5262 newuser->pass = strdup(args[cur_arg + 1]);
5263 newuser->flags |= AU_O_INSECURE;
5264 cur_arg += 2;
5265 continue;
5266 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005267 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005268 cur_arg += 2;
5269 continue;
5270 } else {
5271 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5272 file, linenum, args[0]);
5273 err_code |= ERR_ALERT | ERR_FATAL;
5274 goto out;
5275 }
5276 }
5277 } else {
5278 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5279 err_code |= ERR_ALERT | ERR_FATAL;
5280 }
5281
5282out:
5283 return err_code;
5284}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285
5286/*
5287 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005288 * Returns the error code, 0 if OK, or any combination of :
5289 * - ERR_ABORT: must abort ASAP
5290 * - ERR_FATAL: we can continue parsing but not start the service
5291 * - ERR_WARN: a warning has been emitted
5292 * - ERR_ALERT: an alert has been emitted
5293 * Only the two first ones can stop processing, the two others are just
5294 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005296int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005298 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 FILE *f;
5300 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005302 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 if ((f=fopen(file,"r")) == NULL)
5305 return -1;
5306
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005307 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005308 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005309 char *end;
5310 char *args[MAX_LINE_ARGS + 1];
5311 char *line = thisline;
5312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 linenum++;
5314
5315 end = line + strlen(line);
5316
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005317 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5318 /* Check if we reached the limit and the last char is not \n.
5319 * Watch out for the last line without the terminating '\n'!
5320 */
5321 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005322 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005324 }
5325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005327 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 line++;
5329
5330 arg = 0;
5331 args[arg] = line;
5332
5333 while (*line && arg < MAX_LINE_ARGS) {
5334 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5335 * C equivalent value. Other combinations left unchanged (eg: \1).
5336 */
5337 if (*line == '\\') {
5338 int skip = 0;
5339 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5340 *line = line[1];
5341 skip = 1;
5342 }
5343 else if (line[1] == 'r') {
5344 *line = '\r';
5345 skip = 1;
5346 }
5347 else if (line[1] == 'n') {
5348 *line = '\n';
5349 skip = 1;
5350 }
5351 else if (line[1] == 't') {
5352 *line = '\t';
5353 skip = 1;
5354 }
5355 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005356 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 unsigned char hex1, hex2;
5358 hex1 = toupper(line[2]) - '0';
5359 hex2 = toupper(line[3]) - '0';
5360 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5361 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5362 *line = (hex1<<4) + hex2;
5363 skip = 3;
5364 }
5365 else {
5366 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005367 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 }
5369 }
5370 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005371 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 end -= skip;
5373 }
5374 line++;
5375 }
5376 else if (*line == '#' || *line == '\n' || *line == '\r') {
5377 /* end of string, end of loop */
5378 *line = 0;
5379 break;
5380 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005381 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005383 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005384 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 line++;
5386 args[++arg] = line;
5387 }
5388 else {
5389 line++;
5390 }
5391 }
5392
5393 /* empty line */
5394 if (!**args)
5395 continue;
5396
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005397 if (*line) {
5398 /* we had to stop due to too many args.
5399 * Let's terminate the string, print the offending part then cut the
5400 * last arg.
5401 */
5402 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5403 line++;
5404 *line = '\0';
5405
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005406 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005407 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 args[arg] = line;
5410 }
5411
Willy Tarreau540abe42007-05-02 20:50:16 +02005412 /* zero out remaining args and ensure that at least one entry
5413 * is zeroed out.
5414 */
5415 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 args[arg] = line;
5417 }
5418
Willy Tarreau3842f002009-06-14 11:39:52 +02005419 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005420 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005421 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005422 for (arg=0; *args[arg+1]; arg++)
5423 args[arg] = args[arg+1]; // shift args after inversion
5424 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005425 else if (!strcmp(args[0], "default")) {
5426 kwm = KWM_DEF;
5427 for (arg=0; *args[arg+1]; arg++)
5428 args[arg] = args[arg+1]; // shift args after inversion
5429 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005430
Willy Tarreau3842f002009-06-14 11:39:52 +02005431 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5432 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005433 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005434 }
5435
Willy Tarreau977b8e42006-12-29 14:19:17 +01005436 if (!strcmp(args[0], "listen") ||
5437 !strcmp(args[0], "frontend") ||
5438 !strcmp(args[0], "backend") ||
5439 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005440 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005442 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005443 cursection = strdup(args[0]);
5444 }
5445 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005447 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005448 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005449 }
5450 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005451 confsect = CFG_USERLIST;
5452 free(cursection);
5453 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005454 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005455 else if (!strcmp(args[0], "peers")) {
5456 confsect = CFG_PEERS;
5457 free(cursection);
5458 cursection = strdup(args[0]);
5459 }
5460
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 /* else it's a section keyword */
5462
5463 switch (confsect) {
5464 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 break;
5467 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005468 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005470 case CFG_USERLIST:
5471 err_code |= cfg_parse_users(file, linenum, args, kwm);
5472 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005473 case CFG_PEERS:
5474 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5475 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005477 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005480
5481 if (err_code & ERR_ABORT)
5482 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005484 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005485 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005487 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005488}
5489
Willy Tarreaubb925012009-07-23 13:36:36 +02005490/*
5491 * Returns the error code, 0 if OK, or any combination of :
5492 * - ERR_ABORT: must abort ASAP
5493 * - ERR_FATAL: we can continue parsing but not start the service
5494 * - ERR_WARN: a warning has been emitted
5495 * - ERR_ALERT: an alert has been emitted
5496 * Only the two first ones can stop processing, the two others are just
5497 * indicators.
5498 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005499int check_config_validity()
5500{
5501 int cfgerr = 0;
5502 struct proxy *curproxy = NULL;
5503 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005504 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005505 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005506 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507
5508 /*
5509 * Now, check for the integrity of all that we have collected.
5510 */
5511
5512 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005513 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005515 /* first, we will invert the proxy list order */
5516 curproxy = NULL;
5517 while (proxy) {
5518 struct proxy *next;
5519
5520 next = proxy->next;
5521 proxy->next = curproxy;
5522 curproxy = proxy;
5523 if (!next)
5524 break;
5525 proxy = next;
5526 }
5527
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005529 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 }
5533
5534 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005535 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005536 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005537 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005538 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005539 unsigned int next_id;
5540
5541 if (!curproxy->uuid) {
5542 /* proxy ID not set, use automatic numbering with first
5543 * spare entry starting with next_pxid.
5544 */
5545 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5546 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5547 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005548 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005549 next_pxid++;
5550
Willy Tarreau55ea7572007-06-17 19:56:27 +02005551
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005553 /* ensure we don't keep listeners uselessly bound */
5554 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 curproxy = curproxy->next;
5556 continue;
5557 }
5558
Willy Tarreauff01a212009-03-15 13:46:16 +01005559 switch (curproxy->mode) {
5560 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005561 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005562 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005563 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005565 cfgerr++;
5566 }
5567
5568 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005569 Warning("config : servers will be ignored for %s '%s'.\n",
5570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005571 break;
5572
5573 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005574 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005575 break;
5576
5577 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005578 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 break;
5580 }
5581
5582 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 cfgerr++;
5586 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005587
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005588 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005589 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005590 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005591 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005593 cfgerr++;
5594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005596 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005597 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5598 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005599 cfgerr++;
5600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005602 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005603 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005605 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005606 }
5607 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005608 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005609 /* If no LB algo is set in a backend, and we're not in
5610 * transparent mode, dispatch mode nor proxy mode, we
5611 * want to use balance roundrobin by default.
5612 */
5613 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5614 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
5616 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005617
Willy Tarreau1620ec32011-08-06 17:05:02 +02005618 if (curproxy->options & PR_O_DISPATCH)
5619 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5620 else if (curproxy->options & PR_O_HTTP_PROXY)
5621 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5622 else if (curproxy->options & PR_O_TRANSP)
5623 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005624
Willy Tarreau1620ec32011-08-06 17:05:02 +02005625 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5626 if (curproxy->options & PR_O_DISABLE404) {
5627 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5628 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5629 err_code |= ERR_WARN;
5630 curproxy->options &= ~PR_O_DISABLE404;
5631 }
5632 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5633 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5634 "send-state", proxy_type_str(curproxy), curproxy->id);
5635 err_code |= ERR_WARN;
5636 curproxy->options &= ~PR_O2_CHK_SNDST;
5637 }
Willy Tarreauef781042010-01-27 11:53:01 +01005638 }
5639
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005640 /* if a default backend was specified, let's find it */
5641 if (curproxy->defbe.name) {
5642 struct proxy *target;
5643
Alex Williams96532db2009-11-01 21:27:13 -05005644 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005645 if (!target) {
5646 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5647 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005648 cfgerr++;
5649 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005650 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5651 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005652 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005653 } else {
5654 free(curproxy->defbe.name);
5655 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005656 /* we force the backend to be present on at least all of
5657 * the frontend's processes.
5658 */
5659 target->bind_proc = curproxy->bind_proc ?
5660 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 }
5663
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005664 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005665 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5666 /* map jump target for ACT_SETBE in req_rep chain */
5667 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005668 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005669 struct proxy *target;
5670
Willy Tarreaua496b602006-12-17 23:15:24 +01005671 if (exp->action != ACT_SETBE)
5672 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005673
Alex Williams96532db2009-11-01 21:27:13 -05005674 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005675 if (!target) {
5676 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5677 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005678 cfgerr++;
5679 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005680 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5681 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005682 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 } else {
5684 free((void *)exp->replace);
5685 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005686 /* we force the backend to be present on at least all of
5687 * the frontend's processes.
5688 */
5689 target->bind_proc = curproxy->bind_proc ?
5690 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005691 }
5692 }
5693 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005694
5695 /* find the target proxy for 'use_backend' rules */
5696 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005697 struct proxy *target;
5698
Alex Williams96532db2009-11-01 21:27:13 -05005699 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005700
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005701 if (!target) {
5702 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5703 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005704 cfgerr++;
5705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005706 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5707 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708 cfgerr++;
5709 } else {
5710 free((void *)rule->be.name);
5711 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005712 /* we force the backend to be present on at least all of
5713 * the frontend's processes.
5714 */
5715 target->bind_proc = curproxy->bind_proc ?
5716 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005717 }
5718 }
5719
Emeric Brunb982a3d2010-01-04 15:45:53 +01005720 /* find the target table for 'stick' rules */
5721 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5722 struct proxy *target;
5723
Emeric Brun1d33b292010-01-04 15:47:17 +01005724 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5725 if (mrule->flags & STK_IS_STORE)
5726 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5727
Emeric Brunb982a3d2010-01-04 15:45:53 +01005728 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005729 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005730 else
5731 target = curproxy;
5732
5733 if (!target) {
5734 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5735 curproxy->id, mrule->table.name);
5736 cfgerr++;
5737 }
5738 else if (target->table.size == 0) {
5739 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5740 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5741 cfgerr++;
5742 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005743 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005744 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5745 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5746 cfgerr++;
5747 }
5748 else {
5749 free((void *)mrule->table.name);
5750 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005751 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005752 }
5753 }
5754
5755 /* find the target table for 'store response' rules */
5756 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5757 struct proxy *target;
5758
Emeric Brun1d33b292010-01-04 15:47:17 +01005759 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5760
Emeric Brunb982a3d2010-01-04 15:45:53 +01005761 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005762 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005763 else
5764 target = curproxy;
5765
5766 if (!target) {
5767 Alert("Proxy '%s': unable to find store table '%s'.\n",
5768 curproxy->id, mrule->table.name);
5769 cfgerr++;
5770 }
5771 else if (target->table.size == 0) {
5772 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5773 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5774 cfgerr++;
5775 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005776 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5778 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5779 cfgerr++;
5780 }
5781 else {
5782 free((void *)mrule->table.name);
5783 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005784 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005785 }
5786 }
5787
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005788 /* find the target table for 'tcp-request' layer 4 rules */
5789 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5790 struct proxy *target;
5791
Willy Tarreau56123282010-08-06 19:06:56 +02005792 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005793 continue;
5794
5795 if (trule->act_prm.trk_ctr.table.n)
5796 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5797 else
5798 target = curproxy;
5799
5800 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005801 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5802 curproxy->id, trule->act_prm.trk_ctr.table.n,
5803 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005804 cfgerr++;
5805 }
5806 else if (target->table.size == 0) {
5807 Alert("Proxy '%s': table '%s' used but not configured.\n",
5808 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5809 cfgerr++;
5810 }
5811 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005812 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 +02005813 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5814 cfgerr++;
5815 }
5816 else {
5817 free(trule->act_prm.trk_ctr.table.n);
5818 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005819 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005820 * to pass a list of counters to track and allocate them right here using
5821 * stktable_alloc_data_type().
5822 */
5823 }
5824 }
5825
Willy Tarreaud1f96522010-08-03 19:34:32 +02005826 /* find the target table for 'tcp-request' layer 6 rules */
5827 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5828 struct proxy *target;
5829
Willy Tarreau56123282010-08-06 19:06:56 +02005830 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005831 continue;
5832
5833 if (trule->act_prm.trk_ctr.table.n)
5834 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5835 else
5836 target = curproxy;
5837
5838 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005839 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5840 curproxy->id, trule->act_prm.trk_ctr.table.n,
5841 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005842 cfgerr++;
5843 }
5844 else if (target->table.size == 0) {
5845 Alert("Proxy '%s': table '%s' used but not configured.\n",
5846 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5847 cfgerr++;
5848 }
5849 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005850 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 +02005851 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5852 cfgerr++;
5853 }
5854 else {
5855 free(trule->act_prm.trk_ctr.table.n);
5856 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005857 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005858 * to pass a list of counters to track and allocate them right here using
5859 * stktable_alloc_data_type().
5860 */
5861 }
5862 }
5863
Emeric Brun32da3c42010-09-23 18:39:19 +02005864 if (curproxy->table.peers.name) {
5865 struct peers *curpeers = peers;
5866
5867 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5868 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5869 free((void *)curproxy->table.peers.name);
5870 curproxy->table.peers.p = peers;
5871 break;
5872 }
5873 }
5874
5875 if (!curpeers) {
5876 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5877 curproxy->id, curproxy->table.peers.name);
5878 cfgerr++;
5879 }
5880 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005881 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5882 curproxy->id, localpeer, curpeers->id);
Emeric Brun32da3c42010-09-23 18:39:19 +02005883 cfgerr++;
5884 }
5885 }
5886
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005887 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005888 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005889 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5890 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5891 "proxy", curproxy->id);
5892 cfgerr++;
5893 goto out_uri_auth_compat;
5894 }
5895
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005896 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005897 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005898 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005899 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005900
Willy Tarreau95fa4692010-02-01 13:05:50 +01005901 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5902 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005903
5904 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005905 uri_auth_compat_req[i++] = "realm";
5906 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5907 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005908
Willy Tarreau95fa4692010-02-01 13:05:50 +01005909 uri_auth_compat_req[i++] = "unless";
5910 uri_auth_compat_req[i++] = "{";
5911 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5912 uri_auth_compat_req[i++] = "}";
5913 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914
Willy Tarreauff011f22011-01-06 17:51:27 +01005915 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5916 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005917 cfgerr++;
5918 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005919 }
5920
Willy Tarreauff011f22011-01-06 17:51:27 +01005921 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005922
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005923 if (curproxy->uri_auth->auth_realm) {
5924 free(curproxy->uri_auth->auth_realm);
5925 curproxy->uri_auth->auth_realm = NULL;
5926 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005927
5928 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929 }
5930out_uri_auth_compat:
5931
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005932 cfgerr += acl_find_targets(curproxy);
5933
Willy Tarreau2738a142006-07-08 17:28:09 +02005934 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005935 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005936 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005937 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005938 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005939 " | While not properly invalid, you will certainly encounter various problems\n"
5940 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005941 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005942 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005943 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005944 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005945
Willy Tarreau1fa31262007-12-03 00:36:16 +01005946 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5947 * We must still support older configurations, so let's find out whether those
5948 * parameters have been set or must be copied from contimeouts.
5949 */
5950 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005951 if (!curproxy->timeout.tarpit ||
5952 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005953 /* tarpit timeout not set. We search in the following order:
5954 * default.tarpit, curr.connect, default.connect.
5955 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005956 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005957 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005958 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005959 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005960 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005961 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005962 }
5963 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005964 (!curproxy->timeout.queue ||
5965 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005966 /* queue timeout not set. We search in the following order:
5967 * default.queue, curr.connect, default.connect.
5968 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005969 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005970 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005972 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005974 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005975 }
5976 }
5977
Willy Tarreau1620ec32011-08-06 17:05:02 +02005978 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005979 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5980 curproxy->check_req = (char *)malloc(curproxy->check_len);
5981 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005982 }
5983
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005984 /* The small pools required for the capture lists */
5985 if (curproxy->nb_req_cap)
5986 curproxy->req_cap_pool = create_pool("ptrcap",
5987 curproxy->nb_req_cap * sizeof(char *),
5988 MEM_F_SHARED);
5989 if (curproxy->nb_rsp_cap)
5990 curproxy->rsp_cap_pool = create_pool("ptrcap",
5991 curproxy->nb_rsp_cap * sizeof(char *),
5992 MEM_F_SHARED);
5993
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005994 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5995 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5996 MEM_F_SHARED);
5997
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 /* first, we will invert the servers list order */
5999 newsrv = NULL;
6000 while (curproxy->srv) {
6001 struct server *next;
6002
6003 next = curproxy->srv->next;
6004 curproxy->srv->next = newsrv;
6005 newsrv = curproxy->srv;
6006 if (!next)
6007 break;
6008 curproxy->srv = next;
6009 }
6010
Willy Tarreaudd701652010-05-25 23:03:02 +02006011 /* assign automatic UIDs to servers which don't have one yet */
6012 next_id = 1;
6013 newsrv = curproxy->srv;
6014 while (newsrv != NULL) {
6015 if (!newsrv->puid) {
6016 /* server ID not set, use automatic numbering with first
6017 * spare entry starting with next_svid.
6018 */
6019 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6020 newsrv->conf.id.key = newsrv->puid = next_id;
6021 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6022 }
6023 next_id++;
6024 newsrv = newsrv->next;
6025 }
6026
Willy Tarreau20697042007-11-15 23:26:18 +01006027 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006028 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006029
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006030 /* We have to initialize the server lookup mechanism depending
6031 * on what LB algorithm was choosen.
6032 */
6033
6034 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6035 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6036 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006037 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6038 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6039 init_server_map(curproxy);
6040 } else {
6041 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6042 fwrr_init_server_groups(curproxy);
6043 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006044 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006045
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006046 case BE_LB_KIND_LC:
6047 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006048 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006049 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006050
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006051 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006052 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6053 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6054 chash_init_server_tree(curproxy);
6055 } else {
6056 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6057 init_server_map(curproxy);
6058 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006059 break;
6060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061
6062 if (curproxy->options & PR_O_LOGASAP)
6063 curproxy->to_log &= ~LW_BYTES;
6064
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006065 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6066 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6067 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6068 proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
6070 }
6071
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006072 if (curproxy->mode != PR_MODE_HTTP) {
6073 int optnum;
6074
6075 if (curproxy->options & PR_O_COOK_ANY) {
6076 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6077 proxy_type_str(curproxy), curproxy->id);
6078 err_code |= ERR_WARN;
6079 }
6080
6081 if (curproxy->uri_auth) {
6082 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6083 proxy_type_str(curproxy), curproxy->id);
6084 err_code |= ERR_WARN;
6085 curproxy->uri_auth = NULL;
6086 }
6087
Willy Tarreau87cf5142011-08-19 22:57:24 +02006088 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006089 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6090 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6091 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006092 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006093 }
6094
6095 if (curproxy->options & PR_O_ORGTO) {
6096 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6097 "originalto", proxy_type_str(curproxy), curproxy->id);
6098 err_code |= ERR_WARN;
6099 curproxy->options &= ~PR_O_ORGTO;
6100 }
6101
6102 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6103 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6104 (curproxy->cap & cfg_opts[optnum].cap) &&
6105 (curproxy->options & cfg_opts[optnum].val)) {
6106 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6107 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6108 err_code |= ERR_WARN;
6109 curproxy->options &= ~cfg_opts[optnum].val;
6110 }
6111 }
6112
6113 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6114 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6115 (curproxy->cap & cfg_opts2[optnum].cap) &&
6116 (curproxy->options2 & cfg_opts2[optnum].val)) {
6117 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6118 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6119 err_code |= ERR_WARN;
6120 curproxy->options2 &= ~cfg_opts2[optnum].val;
6121 }
6122 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006123
Willy Tarreauefa5f512010-03-30 20:13:29 +02006124#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006125 if (curproxy->bind_hdr_occ) {
6126 curproxy->bind_hdr_occ = 0;
6127 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6128 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6129 err_code |= ERR_WARN;
6130 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006131#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006132 }
6133
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006135 * ensure that we're not cross-dressing a TCP server into HTTP.
6136 */
6137 newsrv = curproxy->srv;
6138 while (newsrv != NULL) {
6139 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006140 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6141 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006142 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006143 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006144
Willy Tarreauefa5f512010-03-30 20:13:29 +02006145#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006146 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6147 newsrv->bind_hdr_occ = 0;
6148 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6149 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6150 err_code |= ERR_WARN;
6151 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006152#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006153 newsrv = newsrv->next;
6154 }
6155
6156 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 * If this server supports a maxconn parameter, it needs a dedicated
6158 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006159 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 */
6161 newsrv = curproxy->srv;
6162 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006163 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 /* Only 'minconn' was specified, or it was higher than or equal
6165 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6166 * this will avoid further useless expensive computations.
6167 */
6168 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006169 } else if (newsrv->maxconn && !newsrv->minconn) {
6170 /* minconn was not specified, so we set it to maxconn */
6171 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
6173
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006174 if (newsrv->trackit) {
6175 struct proxy *px;
6176 struct server *srv;
6177 char *pname, *sname;
6178
6179 pname = newsrv->trackit;
6180 sname = strrchr(pname, '/');
6181
6182 if (sname)
6183 *sname++ = '\0';
6184 else {
6185 sname = pname;
6186 pname = NULL;
6187 }
6188
6189 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006190 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006191 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006192 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6193 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006194 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006195 cfgerr++;
6196 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006197 }
6198 } else
6199 px = curproxy;
6200
6201 srv = findserver(px, sname);
6202 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6204 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006206 cfgerr++;
6207 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006208 }
6209
6210 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006211 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006212 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006213 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006215 cfgerr++;
6216 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006217 }
6218
6219 if (curproxy != px &&
6220 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006222 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006223 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006224 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006225 cfgerr++;
6226 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006227 }
6228
6229 newsrv->tracked = srv;
6230 newsrv->tracknext = srv->tracknext;
6231 srv->tracknext = newsrv;
6232
6233 free(newsrv->trackit);
6234 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006235 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236 newsrv = newsrv->next;
6237 }
6238
Willy Tarreauc1a21672009-08-16 22:37:44 +02006239 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006240 curproxy->accept = frontend_accept;
6241
Willy Tarreauc1a21672009-08-16 22:37:44 +02006242 if (curproxy->tcp_req.inspect_delay ||
6243 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006244 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006245
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006246 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006247 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006248 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006249 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006250
6251 /* both TCP and HTTP must check switching rules */
6252 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6253 }
6254
6255 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006256 if (curproxy->tcp_req.inspect_delay ||
6257 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6258 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6259
Emeric Brun97679e72010-09-23 17:56:44 +02006260 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6261 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6262
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006263 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006264 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006265 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006266 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006267
6268 /* If the backend does requires RDP cookie persistence, we have to
6269 * enable the corresponding analyser.
6270 */
6271 if (curproxy->options2 & PR_O2_RDPC_PRST)
6272 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6273 }
6274
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006275 listener = NULL;
6276 while (curproxy->listen) {
6277 struct listener *next;
6278
6279 next = curproxy->listen->next;
6280 curproxy->listen->next = listener;
6281 listener = curproxy->listen;
6282
6283 if (!next)
6284 break;
6285
6286 curproxy->listen = next;
6287 }
6288
Willy Tarreaue6b98942007-10-29 01:09:36 +01006289 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006290 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006291 listener = curproxy->listen;
6292 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006293 if (!listener->luid) {
6294 /* listener ID not set, use automatic numbering with first
6295 * spare entry starting with next_luid.
6296 */
6297 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6298 listener->conf.id.key = listener->luid = next_id;
6299 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006300 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006301 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006302
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006303 /* enable separate counters */
6304 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6305 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6306 if (!listener->name) {
6307 sprintf(trash, "sock-%d", listener->luid);
6308 listener->name = strdup(trash);
6309 }
6310 }
6311
Willy Tarreaue6b98942007-10-29 01:09:36 +01006312 if (curproxy->options & PR_O_TCP_NOLING)
6313 listener->options |= LI_O_NOLINGER;
6314 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006315 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006316 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006317 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006318 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006319 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006320 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006321
Willy Tarreau8a956912010-10-15 14:27:08 +02006322 if (listener->options & LI_O_ACC_PROXY)
6323 listener->analysers |= AN_REQ_DECODE_PROXY;
6324
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006325 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6326 listener->options |= LI_O_TCP_RULES;
6327
Willy Tarreaude3041d2010-05-31 10:56:17 +02006328 if (curproxy->mon_mask.s_addr)
6329 listener->options |= LI_O_CHK_MONNET;
6330
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006331 /* smart accept mode is automatic in HTTP mode */
6332 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6333 (curproxy->mode == PR_MODE_HTTP &&
6334 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6335 listener->options |= LI_O_NOQUICKACK;
6336
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006337 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006338 listener = listener->next;
6339 }
6340
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006341 /* Check multi-process mode compatibility for the current proxy */
6342 if (global.nbproc > 1) {
6343 int nbproc = 0;
6344 if (curproxy->bind_proc) {
6345 int proc;
6346 for (proc = 0; proc < global.nbproc; proc++) {
6347 if (curproxy->bind_proc & (1 << proc)) {
6348 nbproc++;
6349 }
6350 }
6351 } else {
6352 nbproc = global.nbproc;
6353 }
6354 if (curproxy->table.peers.name) {
6355 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6356 curproxy->id);
6357 cfgerr++;
6358 }
6359 if (nbproc > 1) {
6360 if (curproxy->uri_auth) {
6361 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6362 curproxy->id);
6363 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6364 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6365 curproxy->id);
6366 }
6367 }
6368 if (curproxy->appsession_name) {
6369 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6370 curproxy->id);
6371 }
6372 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6373 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6374 curproxy->id);
6375 }
6376 }
6377 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006378
6379 /* create the task associated with the proxy */
6380 curproxy->task = task_new();
6381 if (curproxy->task) {
6382 curproxy->task->context = curproxy;
6383 curproxy->task->process = manage_proxy;
6384 /* no need to queue, it will be done automatically if some
6385 * listener gets limited.
6386 */
6387 curproxy->task->expire = TICK_ETERNITY;
6388 } else {
6389 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6390 curproxy->id);
6391 cfgerr++;
6392 }
6393
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 curproxy = curproxy->next;
6395 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006396
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006397 /* Check multi-process mode compatibility */
6398 if (global.nbproc > 1) {
6399 if (global.stats_fe) {
6400 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6401 }
6402 }
6403
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006404 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6405 struct auth_users *curuser;
6406 int g;
6407
6408 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6409 unsigned int group_mask = 0;
6410 char *group = NULL;
6411
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006412 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006413 continue;
6414
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006415 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006416
6417 for (g = 0; g < curuserlist->grpcnt; g++)
6418 if (!strcmp(curuserlist->groups[g], group))
6419 break;
6420
6421 if (g == curuserlist->grpcnt) {
6422 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6423 curuserlist->name, group, curuser->user);
6424 err_code |= ERR_ALERT | ERR_FATAL;
6425 goto out;
6426 }
6427
6428 group_mask |= (1 << g);
6429 }
6430
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006431 free(curuser->u.groups);
6432 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006433 }
6434
6435 for (g = 0; g < curuserlist->grpcnt; g++) {
6436 char *user = NULL;
6437
6438 if (!curuserlist->groupusers[g])
6439 continue;
6440
6441 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6442 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6443 if (!strcmp(curuser->user, user))
6444 break;
6445
6446 if (!curuser) {
6447 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6448 curuserlist->name, user, curuserlist->groups[g]);
6449 err_code |= ERR_ALERT | ERR_FATAL;
6450 goto out;
6451 }
6452
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006453 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006454 }
6455
6456 free(curuserlist->groupusers[g]);
6457 }
6458
6459 free(curuserlist->groupusers);
6460
6461#ifdef DEBUG_AUTH
6462 for (g = 0; g < curuserlist->grpcnt; g++) {
6463 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6464
6465 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6466 if (curuser->group_mask & (1 << g))
6467 fprintf(stderr, " %s", curuser->user);
6468 }
6469
6470 fprintf(stderr, "\n");
6471 }
6472#endif
6473
Willy Tarreaufbb78422011-06-05 15:38:35 +02006474 }
6475
6476 /* automatically compute fullconn if not set. We must not do it in the
6477 * loop above because cross-references are not yet fully resolved.
6478 */
6479 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6480 /* If <fullconn> is not set, let's set it to 10% of the sum of
6481 * the possible incoming frontend's maxconns.
6482 */
6483 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6484 struct proxy *fe;
6485 int total = 0;
6486
6487 /* sum up the number of maxconns of frontends which
6488 * reference this backend at least once or which are
6489 * the same one ('listen').
6490 */
6491 for (fe = proxy; fe; fe = fe->next) {
6492 struct switching_rule *rule;
6493 struct hdr_exp *exp;
6494 int found = 0;
6495
6496 if (!(fe->cap & PR_CAP_FE))
6497 continue;
6498
6499 if (fe == curproxy) /* we're on a "listen" instance */
6500 found = 1;
6501
6502 if (fe->defbe.be == curproxy) /* "default_backend" */
6503 found = 1;
6504
6505 /* check if a "use_backend" rule matches */
6506 if (!found) {
6507 list_for_each_entry(rule, &fe->switching_rules, list) {
6508 if (rule->be.backend == curproxy) {
6509 found = 1;
6510 break;
6511 }
6512 }
6513 }
6514
6515 /* check if a "reqsetbe" rule matches */
6516 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6517 if (exp->action == ACT_SETBE &&
6518 (struct proxy *)exp->replace == curproxy) {
6519 found = 1;
6520 break;
6521 }
6522 }
6523
6524 /* now we've checked all possible ways to reference a backend
6525 * from a frontend.
6526 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006527 if (!found)
6528 continue;
6529 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006530 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006531 /* we have the sum of the maxconns in <total>. We only
6532 * keep 10% of that sum to set the default fullconn, with
6533 * a hard minimum of 1 (to avoid a divide by zero).
6534 */
6535 curproxy->fullconn = (total + 9) / 10;
6536 if (!curproxy->fullconn)
6537 curproxy->fullconn = 1;
6538 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006539 }
6540
Willy Tarreau056f5682010-06-06 15:51:11 +02006541 /* initialize stick-tables on backend capable proxies. This must not
6542 * be done earlier because the data size may be discovered while parsing
6543 * other proxies.
6544 */
6545 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006546 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006547
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006548 /*
6549 * Recount currently required checks.
6550 */
6551
6552 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6553 int optnum;
6554
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006555 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6556 if (curproxy->options & cfg_opts[optnum].val)
6557 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006558
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006559 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6560 if (curproxy->options2 & cfg_opts2[optnum].val)
6561 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562 }
6563
Willy Tarreau122541c2011-09-07 21:24:49 +02006564 if (peers) {
6565 struct peers *curpeers = peers, **last;
6566 struct peer *p, *pb;
6567
6568 /* Remove all peers sections which don't have a valid listener.
6569 * This can happen when a peers section is never referenced and
6570 * does not contain a local peer.
6571 */
6572 last = &peers;
6573 while (*last) {
6574 curpeers = *last;
6575 if (curpeers->peers_fe) {
6576 last = &curpeers->next;
6577 continue;
6578 }
6579
6580 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6581 curpeers->id, localpeer);
6582
6583 p = curpeers->remote;
6584 while (p) {
6585 pb = p->next;
6586 free(p->id);
6587 free(p);
6588 p = pb;
6589 }
6590
6591 /* Destroy and unlink this curpeers section.
6592 * Note: curpeers is backed up into *last.
6593 */
6594 free(curpeers->id);
6595 curpeers = curpeers->next;
6596 free(*last);
6597 *last = curpeers;
6598 }
6599 }
6600
Willy Tarreaubb925012009-07-23 13:36:36 +02006601 if (cfgerr > 0)
6602 err_code |= ERR_ALERT | ERR_FATAL;
6603 out:
6604 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605}
6606
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006607/*
6608 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6609 * parsing sessions.
6610 */
6611void cfg_register_keywords(struct cfg_kw_list *kwl)
6612{
6613 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6614}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006615
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006616/*
6617 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6618 */
6619void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6620{
6621 LIST_DEL(&kwl->list);
6622 LIST_INIT(&kwl->list);
6623}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006624
6625/*
6626 * Local variables:
6627 * c-indent-level: 8
6628 * c-basic-offset: 8
6629 * End:
6630 */