blob: fd81a203e8fbf4b200d12bf22071340763b3c045 [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 Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 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 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 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 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 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);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau97cb7802010-01-03 20:23:58 +01001023/* Perform the most basic initialization of a proxy :
1024 * memset(), list_init(*), reset_timeouts(*).
1025 */
1026static void init_new_proxy(struct proxy *p)
1027{
1028 memset(p, 0, sizeof(struct proxy));
1029 LIST_INIT(&p->pendconns);
1030 LIST_INIT(&p->acl);
Willy Tarreauff011f22011-01-06 17:51:27 +01001031 LIST_INIT(&p->http_req_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001032 LIST_INIT(&p->block_cond);
1033 LIST_INIT(&p->redirect_rules);
1034 LIST_INIT(&p->mon_fail_cond);
1035 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001036 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001037 LIST_INIT(&p->sticking_rules);
1038 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001039 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001040 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001041 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001042 LIST_INIT(&p->req_add);
1043 LIST_INIT(&p->rsp_add);
Willy Tarreau07687c12011-07-24 23:55:06 +02001044 LIST_INIT(&p->listener_queue);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001045
1046 /* Timeouts are defined as -1 */
1047 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001048 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001049}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001051void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001053 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054 defproxy.mode = PR_MODE_TCP;
1055 defproxy.state = PR_STNEW;
1056 defproxy.maxconn = cfg_maxpconn;
1057 defproxy.conn_retries = CONN_RETRIES;
1058 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001059
1060 defproxy.defsrv.inter = DEF_CHKINTR;
1061 defproxy.defsrv.fastinter = 0;
1062 defproxy.defsrv.downinter = 0;
1063 defproxy.defsrv.rise = DEF_RISETIME;
1064 defproxy.defsrv.fall = DEF_FALLTIME;
1065 defproxy.defsrv.check_port = 0;
1066 defproxy.defsrv.maxqueue = 0;
1067 defproxy.defsrv.minconn = 0;
1068 defproxy.defsrv.maxconn = 0;
1069 defproxy.defsrv.slowstart = 0;
1070 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1071 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1072 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073}
1074
Willy Tarreauade5ec42010-01-28 19:33:49 +01001075
1076static int create_cond_regex_rule(const char *file, int line,
1077 struct proxy *px, int dir, int action, int flags,
1078 const char *cmd, const char *reg, const char *repl,
1079 const char **cond_start)
1080{
1081 regex_t *preg = NULL;
1082 const char *err;
1083 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001084 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001085
1086 if (px == &defproxy) {
1087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto err;
1090 }
1091
1092 if (*reg == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto err;
1096 }
1097
1098 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1099 err_code |= ERR_WARN;
1100
Willy Tarreau5321c422010-01-28 20:35:13 +01001101 if (cond_start &&
1102 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1103 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1104 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1105 file, line, cmd);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto err;
1108 }
1109 }
1110 else if (cond_start && **cond_start) {
1111 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1112 file, line, cmd, *cond_start);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto err;
1115 }
1116
1117 if (dir == ACL_DIR_REQ)
1118 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001119 else
1120 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001121
Willy Tarreauade5ec42010-01-28 19:33:49 +01001122 preg = calloc(1, sizeof(regex_t));
1123 if (!preg) {
1124 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1125 err_code = ERR_ALERT | ERR_FATAL;
1126 goto err;
1127 }
1128
1129 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1130 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1131 err_code = ERR_ALERT | ERR_FATAL;
1132 goto err;
1133 }
1134
1135 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001136 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001137 if (repl && err) {
1138 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1139 file, line, cmd, *err);
1140 err_code |= ERR_ALERT | ERR_FATAL;
1141 goto err;
1142 }
1143
1144 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1145 err_code |= ERR_WARN;
1146
1147 return err_code;
1148 err:
1149 free(preg);
1150 return err_code;
1151}
1152
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001154 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001155 * Returns the error code, 0 if OK, or any combination of :
1156 * - ERR_ABORT: must abort ASAP
1157 * - ERR_FATAL: we can continue parsing but not start the service
1158 * - ERR_WARN: a warning has been emitted
1159 * - ERR_ALERT: an alert has been emitted
1160 * Only the two first ones can stop processing, the two others are just
1161 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001163int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1164{
1165 static struct peers *curpeers = NULL;
1166 struct peer *newpeer = NULL;
1167 const char *err;
1168 int err_code = 0;
1169
1170 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1171
1172 err = invalid_char(args[1]);
1173 if (err) {
1174 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1175 file, linenum, *err, args[0], args[1]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 }
1178
1179 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1180 /*
1181 * If there are two proxies with the same name only following
1182 * combinations are allowed:
1183 */
1184 if (strcmp(curpeers->id, args[1]) == 0) {
1185 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1186 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1187 err_code |= ERR_WARN;
1188 }
1189 }
1190
1191 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1193 err_code |= ERR_ALERT | ERR_ABORT;
1194 goto out;
1195 }
1196
1197 curpeers->next = peers;
1198 peers = curpeers;
1199 curpeers->conf.file = file;
1200 curpeers->conf.line = linenum;
1201 curpeers->last_change = now.tv_sec;
1202 curpeers->id = strdup(args[1]);
1203 }
1204 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1205 char *rport, *raddr;
1206 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001207 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001208
1209 if (!*args[2]) {
1210 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1211 file, linenum, args[0]);
1212 err_code |= ERR_ALERT | ERR_FATAL;
1213 goto out;
1214 }
1215
1216 err = invalid_char(args[1]);
1217 if (err) {
1218 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1219 file, linenum, *err, args[1]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223
1224 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1225 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1226 err_code |= ERR_ALERT | ERR_ABORT;
1227 goto out;
1228 }
1229
1230 /* the peers are linked backwards first */
1231 curpeers->count++;
1232 newpeer->next = curpeers->remote;
1233 curpeers->remote = newpeer;
1234 newpeer->peers = curpeers;
1235 newpeer->conf.file = file;
1236 newpeer->conf.line = linenum;
1237
1238 newpeer->last_change = now.tv_sec;
1239 newpeer->id = strdup(args[1]);
1240
1241 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001242 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001243 if (rport) {
1244 *rport++ = 0;
1245 realport = atol(rport);
1246 }
1247 if (!realport) {
1248 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252
Willy Tarreaufab5a432011-03-04 15:31:53 +01001253 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001254 free(raddr);
1255 if (!sk) {
1256 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001261
1262 switch (newpeer->addr.ss_family) {
1263 case AF_INET:
1264 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1265 break;
1266 case AF_INET6:
1267 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1268 break;
1269 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001270
1271 if (strcmp(newpeer->id, localpeer) == 0) {
1272 /* Current is local peer, it define a frontend */
1273 newpeer->local = 1;
1274
1275 if (!curpeers->peers_fe) {
1276 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1278 err_code |= ERR_ALERT | ERR_ABORT;
1279 goto out;
1280 }
1281 curpeers->peers_fe->parent = curpeers;
1282
1283 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1284 LIST_INIT(&(curpeers->peers_fe)->acl);
1285 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1286 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1287 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1288 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1289 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1290 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1291
1292 proxy_reset_timeouts(curpeers->peers_fe);
1293
1294 curpeers->peers_fe->last_change = now.tv_sec;
1295 curpeers->peers_fe->id = strdup(args[1]);
1296 curpeers->peers_fe->cap = PR_CAP_FE;
1297 curpeers->peers_fe->maxconn = 65000;
1298 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1299 curpeers->peers_fe->timeout.connect = 5000;
1300 curpeers->peers_fe->accept = peer_accept;
1301 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001302 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 err_code |= ERR_FATAL;
1304 goto out;
1305 }
1306 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1307 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1308 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1309 curpeers->peers_fe->listen->accept = session_accept;
1310 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1311 curpeers->peers_fe->listen->handler = process_session;
1312 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1313 }
1314 }
1315 } /* neither "peer" nor "peers" */
1316 else if (*args[0] != 0) {
1317 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
1321
1322out:
1323 return err_code;
1324}
1325
1326
Willy Tarreau3842f002009-06-14 11:39:52 +02001327int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328{
1329 static struct proxy *curproxy = NULL;
1330 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001331 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001332 int rc;
1333 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001334 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001335 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336
Willy Tarreau977b8e42006-12-29 14:19:17 +01001337 if (!strcmp(args[0], "listen"))
1338 rc = PR_CAP_LISTEN;
1339 else if (!strcmp(args[0], "frontend"))
1340 rc = PR_CAP_FE | PR_CAP_RS;
1341 else if (!strcmp(args[0], "backend"))
1342 rc = PR_CAP_BE | PR_CAP_RS;
1343 else if (!strcmp(args[0], "ruleset"))
1344 rc = PR_CAP_RS;
1345 else
1346 rc = PR_CAP_NONE;
1347
1348 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if (!*args[1]) {
1350 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1351 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1352 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001353 err_code |= ERR_ALERT | ERR_ABORT;
1354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001356
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001357 err = invalid_char(args[1]);
1358 if (err) {
1359 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1360 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001362 }
1363
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001364 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1365 /*
1366 * If there are two proxies with the same name only following
1367 * combinations are allowed:
1368 *
1369 * listen backend frontend ruleset
1370 * listen - - - -
1371 * backend - - OK -
1372 * frontend - OK - -
1373 * ruleset - - - -
1374 */
1375
1376 if (!strcmp(curproxy->id, args[1]) &&
1377 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1378 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001379 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1380 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1381 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001383 }
1384 }
1385
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001388 err_code |= ERR_ALERT | ERR_ABORT;
1389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001391
Willy Tarreau97cb7802010-01-03 20:23:58 +01001392 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 curproxy->next = proxy;
1394 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001395 curproxy->conf.file = file;
1396 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001397 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001399 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400
1401 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001402 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001403 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001404 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001405 err_code |= ERR_FATAL;
1406 goto out;
1407 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001408 new = curproxy->listen;
1409 while (new != last) {
1410 new->conf.file = file;
1411 new->conf.line = linenum;
1412 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001413 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001414 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 }
1416
1417 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001418 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001419 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001420
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001423 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001424 curproxy->no_options = defproxy.no_options;
1425 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001426 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001427 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001428 curproxy->except_net = defproxy.except_net;
1429 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001430 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001431 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001433 if (defproxy.fwdfor_hdr_len) {
1434 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1435 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1436 }
1437
Willy Tarreaub86db342009-11-30 11:50:16 +01001438 if (defproxy.orgto_hdr_len) {
1439 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1440 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1441 }
1442
Willy Tarreau977b8e42006-12-29 14:19:17 +01001443 if (curproxy->cap & PR_CAP_FE) {
1444 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001445 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001446 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447
1448 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001449 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1450 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001451
1452 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
Willy Tarreau977b8e42006-12-29 14:19:17 +01001455 if (curproxy->cap & PR_CAP_BE) {
1456 curproxy->fullconn = defproxy.fullconn;
1457 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001459 if (defproxy.check_req) {
1460 curproxy->check_req = calloc(1, defproxy.check_len);
1461 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1462 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 if (defproxy.cookie_name)
1466 curproxy->cookie_name = strdup(defproxy.cookie_name);
1467 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001468 if (defproxy.cookie_domain)
1469 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001470
Willy Tarreau31936852010-10-06 16:59:56 +02001471 if (defproxy.cookie_maxidle)
1472 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1473
1474 if (defproxy.cookie_maxlife)
1475 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1476
Emeric Brun647caf12009-06-30 17:57:00 +02001477 if (defproxy.rdp_cookie_name)
1478 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1479 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1480
Willy Tarreau01732802007-11-01 22:48:15 +01001481 if (defproxy.url_param_name)
1482 curproxy->url_param_name = strdup(defproxy.url_param_name);
1483 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001484
Benoitaffb4812009-03-25 13:02:10 +01001485 if (defproxy.hh_name)
1486 curproxy->hh_name = strdup(defproxy.hh_name);
1487 curproxy->hh_len = defproxy.hh_len;
1488 curproxy->hh_match_domain = defproxy.hh_match_domain;
1489
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001490 if (defproxy.iface_name)
1491 curproxy->iface_name = strdup(defproxy.iface_name);
1492 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001495 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496 if (defproxy.capture_name)
1497 curproxy->capture_name = strdup(defproxy.capture_name);
1498 curproxy->capture_namelen = defproxy.capture_namelen;
1499 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001503 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001504 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001505 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001506 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 curproxy->uri_auth = defproxy.uri_auth;
1508 curproxy->mon_net = defproxy.mon_net;
1509 curproxy->mon_mask = defproxy.mon_mask;
1510 if (defproxy.monitor_uri)
1511 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1512 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001513 if (defproxy.defbe.name)
1514 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 }
1516
1517 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001518 curproxy->timeout.connect = defproxy.timeout.connect;
1519 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001520 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001521 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001522 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001523 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001524 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 curproxy->source_addr = defproxy.source_addr;
1526 }
1527
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 curproxy->mode = defproxy.mode;
1529 curproxy->logfac1 = defproxy.logfac1;
1530 curproxy->logsrv1 = defproxy.logsrv1;
1531 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001532 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 curproxy->logfac2 = defproxy.logfac2;
1534 curproxy->logsrv2 = defproxy.logsrv2;
1535 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001536 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001538 curproxy->conf.used_listener_id = EB_ROOT;
1539 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001540
Willy Tarreau93893792009-07-23 13:19:11 +02001541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542 }
1543 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1544 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001545 /* FIXME-20070101: we should do this too at the end of the
1546 * config parsing to free all default values.
1547 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001548 free(defproxy.check_req);
1549 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001550 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001551 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001552 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001553 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001554 free(defproxy.capture_name);
1555 free(defproxy.monitor_uri);
1556 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001557 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001558 free(defproxy.fwdfor_hdr_name);
1559 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001560 free(defproxy.orgto_hdr_name);
1561 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001562
Willy Tarreaua534fea2008-08-03 12:19:50 +02001563 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001564 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001565
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 /* we cannot free uri_auth because it might already be used */
1567 init_default_instance();
1568 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001569 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
1572 else if (curproxy == NULL) {
1573 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
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 }
1577
Willy Tarreau977b8e42006-12-29 14:19:17 +01001578
1579 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001581 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001582 int cur_arg;
1583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 if (curproxy == &defproxy) {
1585 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
1587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001589 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001590 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591
Emeric Bruned760922010-10-22 17:59:25 +02001592 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001593 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001598
1599 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001600
1601 /* NOTE: the following line might create several listeners if there
1602 * are comma-separated IPs or port ranges. So all further processing
1603 * will have to be applied to all listeners created after last_listen.
1604 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001605 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001606 err_code |= ERR_ALERT | ERR_FATAL;
1607 goto out;
1608 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001609
Willy Tarreau90a570f2009-10-04 20:54:54 +02001610 new_listen = curproxy->listen;
1611 while (new_listen != last_listen) {
1612 new_listen->conf.file = file;
1613 new_listen->conf.line = linenum;
1614 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001615 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001616 }
1617
Emeric Bruned760922010-10-22 17:59:25 +02001618 /* Set default global rights and owner for unix bind */
1619 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1620 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1621 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001622 cur_arg = 2;
1623 while (*(args[cur_arg])) {
1624 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1625#ifdef SO_BINDTODEVICE
1626 struct listener *l;
1627
Emeric Bruned760922010-10-22 17:59:25 +02001628 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1629 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1630 file, linenum, args[0], args[cur_arg]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
1634
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001635 if (!*args[cur_arg + 1]) {
1636 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001640 }
1641
1642 for (l = curproxy->listen; l != last_listen; l = l->next)
1643 l->interface = strdup(args[cur_arg + 1]);
1644
1645 global.last_checks |= LSTCHK_NETADM;
1646
1647 cur_arg += 2;
1648 continue;
1649#else
1650 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1651 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001654#endif
1655 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001656 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1657#ifdef TCP_MAXSEG
1658 struct listener *l;
1659 int mss;
1660
Emeric Bruned760922010-10-22 17:59:25 +02001661 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1662 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1663 file, linenum, args[0], args[cur_arg]);
1664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
1666 }
1667
Willy Tarreaube1b9182009-06-14 18:48:19 +02001668 if (!*args[cur_arg + 1]) {
1669 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1670 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001673 }
1674
Willy Tarreau48a7e722010-12-24 15:26:39 +01001675 mss = atoi(args[cur_arg + 1]);
1676 if (!mss || abs(mss) > 65535) {
1677 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001678 file, linenum, args[0]);
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 }
1682
1683 for (l = curproxy->listen; l != last_listen; l = l->next)
1684 l->maxseg = mss;
1685
1686 cur_arg += 2;
1687 continue;
1688#else
1689 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1690 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001693#endif
1694 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001695
1696 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1697#ifdef TCP_DEFER_ACCEPT
1698 struct listener *l;
1699
1700 for (l = curproxy->listen; l != last_listen; l = l->next)
1701 l->options |= LI_O_DEF_ACCEPT;
1702
1703 cur_arg ++;
1704 continue;
1705#else
1706 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1707 file, linenum, args[0], args[cur_arg]);
1708 err_code |= ERR_ALERT | ERR_FATAL;
1709 goto out;
1710#endif
1711 }
1712
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001714#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001715 struct listener *l;
1716
Emeric Bruned760922010-10-22 17:59:25 +02001717 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1718 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1719 file, linenum, args[0], args[cur_arg]);
1720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001724 for (l = curproxy->listen; l != last_listen; l = l->next)
1725 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001726
1727 cur_arg ++;
1728 continue;
1729#else
1730 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1731 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001732 err_code |= ERR_ALERT | ERR_FATAL;
1733 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001734#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001736
Willy Tarreau8a956912010-10-15 14:27:08 +02001737 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1738 struct listener *l;
1739
1740 for (l = curproxy->listen; l != last_listen; l = l->next)
1741 l->options |= LI_O_ACC_PROXY;
1742
1743 cur_arg ++;
1744 continue;
1745 }
1746
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001747 if (!strcmp(args[cur_arg], "name")) {
1748 struct listener *l;
1749
1750 for (l = curproxy->listen; l != last_listen; l = l->next)
1751 l->name = strdup(args[cur_arg + 1]);
1752
1753 cur_arg += 2;
1754 continue;
1755 }
1756
1757 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001758 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001759 struct listener *l;
1760
1761 if (curproxy->listen->next != last_listen) {
1762 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1763 file, linenum, args[cur_arg]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
1768 if (!*args[cur_arg + 1]) {
1769 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1770 file, linenum, args[cur_arg]);
1771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
1773 }
1774
1775 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001776 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001777
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001778 if (curproxy->listen->luid <= 0) {
1779 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001780 file, linenum);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001785 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1786 if (node) {
1787 l = container_of(node, struct listener, conf.id);
1788 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1789 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1794
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001795 cur_arg += 2;
1796 continue;
1797 }
1798
Emeric Bruned760922010-10-22 17:59:25 +02001799 if (!strcmp(args[cur_arg], "mode")) {
1800
1801 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1802 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1803 file, linenum, args[0], args[cur_arg]);
1804 err_code |= ERR_ALERT | ERR_FATAL;
1805 goto out;
1806 }
1807
1808 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1809
1810 cur_arg += 2;
1811 continue;
1812 }
1813
1814 if (!strcmp(args[cur_arg], "uid")) {
1815
1816 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1817 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1818 file, linenum, args[0], args[cur_arg]);
1819 err_code |= ERR_ALERT | ERR_FATAL;
1820 goto out;
1821 }
1822
1823 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1824 cur_arg += 2;
1825 continue;
1826 }
1827
1828 if (!strcmp(args[cur_arg], "gid")) {
1829
1830 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1831 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1832 file, linenum, args[0], args[cur_arg]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836
1837 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1838 cur_arg += 2;
1839 continue;
1840 }
1841
1842 if (!strcmp(args[cur_arg], "user")) {
1843 struct passwd *user;
1844
1845 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1846 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1847 file, linenum, args[0], args[cur_arg]);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851 user = getpwnam(args[cur_arg + 1]);
1852 if (!user) {
1853 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1854 file, linenum, args[0], args[cur_arg + 1 ]);
1855 err_code |= ERR_ALERT | ERR_FATAL;
1856 goto out;
1857 }
1858
1859 curproxy->listen->perm.ux.uid = user->pw_uid;
1860 cur_arg += 2;
1861 continue;
1862 }
1863
1864 if (!strcmp(args[cur_arg], "group")) {
1865 struct group *group;
1866
1867 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1868 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1869 file, linenum, args[0], args[cur_arg]);
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872 }
1873 group = getgrnam(args[cur_arg + 1]);
1874 if (!group) {
1875 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1876 file, linenum, args[0], args[cur_arg + 1 ]);
1877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
1879 }
1880
1881 curproxy->listen->perm.ux.gid = group->gr_gid;
1882 cur_arg += 2;
1883 continue;
1884 }
1885
Willy Tarreau8a956912010-10-15 14:27:08 +02001886 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001890 }
Willy Tarreau93893792009-07-23 13:19:11 +02001891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 }
1893 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1894 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1895 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 /* flush useless bits */
1904 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001907 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001908 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001910
Willy Tarreau1c47f852006-07-09 08:22:27 +02001911 if (!*args[1]) {
1912 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1913 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
1915 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001916 }
1917
Willy Tarreaua534fea2008-08-03 12:19:50 +02001918 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001919 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001920 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001921 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001922 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1923
Willy Tarreau93893792009-07-23 13:19:11 +02001924 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1927 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1928 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1929 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1930 else {
1931 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 }
1935 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001936 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001937 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001938
1939 if (curproxy == &defproxy) {
1940 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001944 }
1945
1946 if (!*args[1]) {
1947 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001951 }
1952
1953 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001954 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001955
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001956 if (curproxy->uuid <= 0) {
1957 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001958 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001961 }
1962
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001963 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1964 if (node) {
1965 struct proxy *target = container_of(node, struct proxy, conf.id);
1966 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1967 file, linenum, proxy_type_str(curproxy), curproxy->id,
1968 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1969 err_code |= ERR_ALERT | ERR_FATAL;
1970 goto out;
1971 }
1972 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001973 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001974 else if (!strcmp(args[0], "description")) {
1975 int i, len=0;
1976 char *d;
1977
Cyril Bonté99ed3272010-01-24 23:29:44 +01001978 if (curproxy == &defproxy) {
1979 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1980 file, linenum, args[0]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001985 if (!*args[1]) {
1986 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1987 file, linenum, args[0]);
1988 return -1;
1989 }
1990
1991 for(i=1; *args[i]; i++)
1992 len += strlen(args[i])+1;
1993
1994 d = (char *)calloc(1, len);
1995 curproxy->desc = d;
1996
1997 d += sprintf(d, "%s", args[1]);
1998 for(i=2; *args[i]; i++)
1999 d += sprintf(d, " %s", args[i]);
2000
2001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2003 curproxy->state = PR_STSTOPPED;
2004 }
2005 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2006 curproxy->state = PR_STNEW;
2007 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002008 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2009 int cur_arg = 1;
2010 unsigned int set = 0;
2011
2012 while (*args[cur_arg]) {
2013 int u;
2014 if (strcmp(args[cur_arg], "all") == 0) {
2015 set = 0;
2016 break;
2017 }
2018 else if (strcmp(args[cur_arg], "odd") == 0) {
2019 set |= 0x55555555;
2020 }
2021 else if (strcmp(args[cur_arg], "even") == 0) {
2022 set |= 0xAAAAAAAA;
2023 }
2024 else {
2025 u = str2uic(args[cur_arg]);
2026 if (u < 1 || u > 32) {
2027 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2028 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002029 err_code |= ERR_ALERT | ERR_FATAL;
2030 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002031 }
2032 if (u > global.nbproc) {
2033 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002036 }
2037 set |= 1 << (u - 1);
2038 }
2039 cur_arg++;
2040 }
2041 curproxy->bind_proc = set;
2042 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002043 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002044 if (curproxy == &defproxy) {
2045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002046 err_code |= ERR_ALERT | ERR_FATAL;
2047 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002048 }
2049
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002050 err = invalid_char(args[1]);
2051 if (err) {
2052 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2053 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002055 }
2056
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002057 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2058 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2059 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002060 err_code |= ERR_ALERT | ERR_FATAL;
2061 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002062 }
2063 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2065 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002068 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002069
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 if (*(args[1]) == 0) {
2071 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2072 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
2074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002076
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002077 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002078 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002079 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002080 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002081 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 curproxy->cookie_name = strdup(args[1]);
2083 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002084
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 cur_arg = 2;
2086 while (*(args[cur_arg])) {
2087 if (!strcmp(args[cur_arg], "rewrite")) {
2088 curproxy->options |= PR_O_COOK_RW;
2089 }
2090 else if (!strcmp(args[cur_arg], "indirect")) {
2091 curproxy->options |= PR_O_COOK_IND;
2092 }
2093 else if (!strcmp(args[cur_arg], "insert")) {
2094 curproxy->options |= PR_O_COOK_INS;
2095 }
2096 else if (!strcmp(args[cur_arg], "nocache")) {
2097 curproxy->options |= PR_O_COOK_NOC;
2098 }
2099 else if (!strcmp(args[cur_arg], "postonly")) {
2100 curproxy->options |= PR_O_COOK_POST;
2101 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002102 else if (!strcmp(args[cur_arg], "preserve")) {
2103 curproxy->options2 |= PR_O2_COOK_PSV;
2104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 else if (!strcmp(args[cur_arg], "prefix")) {
2106 curproxy->options |= PR_O_COOK_PFX;
2107 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002108 else if (!strcmp(args[cur_arg], "domain")) {
2109 if (!*args[cur_arg + 1]) {
2110 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2111 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002114 }
2115
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002116 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002117 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002118 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2119 " dots nor does not start with a dot."
2120 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002121 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002122 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002123 }
2124
2125 err = invalid_domainchar(args[cur_arg + 1]);
2126 if (err) {
2127 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2128 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_ALERT | ERR_FATAL;
2130 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002131 }
2132
Willy Tarreau68a897b2009-12-03 23:28:34 +01002133 if (!curproxy->cookie_domain) {
2134 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2135 } else {
2136 /* one domain was already specified, add another one by
2137 * building the string which will be returned along with
2138 * the cookie.
2139 */
2140 char *new_ptr;
2141 int new_len = strlen(curproxy->cookie_domain) +
2142 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2143 new_ptr = malloc(new_len);
2144 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2145 free(curproxy->cookie_domain);
2146 curproxy->cookie_domain = new_ptr;
2147 }
Willy Tarreau31936852010-10-06 16:59:56 +02002148 cur_arg++;
2149 }
2150 else if (!strcmp(args[cur_arg], "maxidle")) {
2151 unsigned int maxidle;
2152 const char *res;
2153
2154 if (!*args[cur_arg + 1]) {
2155 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2156 file, linenum, args[cur_arg]);
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
2161 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2162 if (res) {
2163 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2164 file, linenum, *res, args[cur_arg]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168 curproxy->cookie_maxidle = maxidle;
2169 cur_arg++;
2170 }
2171 else if (!strcmp(args[cur_arg], "maxlife")) {
2172 unsigned int maxlife;
2173 const char *res;
2174
2175 if (!*args[cur_arg + 1]) {
2176 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2177 file, linenum, args[cur_arg]);
2178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
2180 }
2181
2182 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2183 if (res) {
2184 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2185 file, linenum, *res, args[cur_arg]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
2189 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002190 cur_arg++;
2191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002193 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198 cur_arg++;
2199 }
2200 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2201 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2202 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002203 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 }
2205
2206 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2207 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2208 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002211
2212 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2213 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2214 file, linenum);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002218 else if (!strcmp(args[0], "persist")) { /* persist */
2219 if (*(args[1]) == 0) {
2220 Alert("parsing [%s:%d] : missing persist method.\n",
2221 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
2223 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002224 }
2225
2226 if (!strncmp(args[1], "rdp-cookie", 10)) {
2227 curproxy->options2 |= PR_O2_RDPC_PRST;
2228
Emeric Brunb982a3d2010-01-04 15:45:53 +01002229 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002230 const char *beg, *end;
2231
2232 beg = args[1] + 11;
2233 end = strchr(beg, ')');
2234
2235 if (!end || end == beg) {
2236 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2237 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002238 err_code |= ERR_ALERT | ERR_FATAL;
2239 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002240 }
2241
2242 free(curproxy->rdp_cookie_name);
2243 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2244 curproxy->rdp_cookie_len = end-beg;
2245 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002246 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002247 free(curproxy->rdp_cookie_name);
2248 curproxy->rdp_cookie_name = strdup("msts");
2249 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2250 }
2251 else { /* syntax */
2252 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2253 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002256 }
2257 }
2258 else {
2259 Alert("parsing [%s:%d] : unknown persist method.\n",
2260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002261 err_code |= ERR_ALERT | ERR_FATAL;
2262 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002263 }
2264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002266 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002278 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 }
2283 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002284 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 curproxy->appsession_name = strdup(args[1]);
2286 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2287 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002288 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2289 if (err) {
2290 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2291 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002294 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002295 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002296
Willy Tarreau51041c72007-09-09 21:56:53 +02002297 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_ABORT;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002302
2303 cur_arg = 6;
2304 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002305 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2306 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002307 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002308 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002309 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002310 } else if (!strcmp(args[cur_arg], "prefix")) {
2311 curproxy->options2 |= PR_O2_AS_PFX;
2312 } else if (!strcmp(args[cur_arg], "mode")) {
2313 if (!*args[cur_arg + 1]) {
2314 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2315 file, linenum, args[0], args[cur_arg]);
2316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
2318 }
2319
2320 cur_arg++;
2321 if (!strcmp(args[cur_arg], "query-string")) {
2322 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2323 curproxy->options2 |= PR_O2_AS_M_QS;
2324 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2325 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2326 curproxy->options2 |= PR_O2_AS_M_PP;
2327 } else {
2328 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
2331 }
2332 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002333 cur_arg++;
2334 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 } /* Url App Session */
2336 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002337 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002339
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002341 if (curproxy == &defproxy) {
2342 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
2345 }
2346
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 if (*(args[4]) == 0) {
2348 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2349 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002350 err_code |= ERR_ALERT | ERR_FATAL;
2351 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002353 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 curproxy->capture_name = strdup(args[2]);
2355 curproxy->capture_namelen = strlen(curproxy->capture_name);
2356 curproxy->capture_len = atol(args[4]);
2357 if (curproxy->capture_len >= CAPTURE_LEN) {
2358 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2359 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 curproxy->capture_len = CAPTURE_LEN - 1;
2362 }
2363 curproxy->to_log |= LW_COOKIE;
2364 }
2365 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2366 struct cap_hdr *hdr;
2367
2368 if (curproxy == &defproxy) {
2369 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373
2374 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2375 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2376 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
2380
2381 hdr = calloc(sizeof(struct cap_hdr), 1);
2382 hdr->next = curproxy->req_cap;
2383 hdr->name = strdup(args[3]);
2384 hdr->namelen = strlen(args[3]);
2385 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002386 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 hdr->index = curproxy->nb_req_cap++;
2388 curproxy->req_cap = hdr;
2389 curproxy->to_log |= LW_REQHDR;
2390 }
2391 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2392 struct cap_hdr *hdr;
2393
2394 if (curproxy == &defproxy) {
2395 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399
2400 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2401 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2402 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 }
2406 hdr = calloc(sizeof(struct cap_hdr), 1);
2407 hdr->next = curproxy->rsp_cap;
2408 hdr->name = strdup(args[3]);
2409 hdr->namelen = strlen(args[3]);
2410 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002411 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 hdr->index = curproxy->nb_rsp_cap++;
2413 curproxy->rsp_cap = hdr;
2414 curproxy->to_log |= LW_RSPHDR;
2415 }
2416 else {
2417 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002426
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 if (*(args[1]) == 0) {
2428 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2429 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 curproxy->conn_retries = atol(args[1]);
2434 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002435 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002436 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002437
2438 if (curproxy == &defproxy) {
2439 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
2442 }
2443
Willy Tarreauff011f22011-01-06 17:51:27 +01002444 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002445 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_WARN;
2448 }
2449
Willy Tarreauff011f22011-01-06 17:51:27 +01002450 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002451
Willy Tarreauff011f22011-01-06 17:51:27 +01002452 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002453 err_code |= ERR_ALERT | ERR_ABORT;
2454 goto out;
2455 }
2456
Willy Tarreauff011f22011-01-06 17:51:27 +01002457 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2458 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002459 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002460 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002461 if (curproxy == &defproxy) {
2462 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002463 err_code |= ERR_ALERT | ERR_FATAL;
2464 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002465 }
2466
Willy Tarreauef6494c2010-01-28 17:12:36 +01002467 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002468 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2469 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002472 }
2473
Willy Tarreauef6494c2010-01-28 17:12:36 +01002474 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002475 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002479 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002480
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002481 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002482 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002483 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002485 struct redirect_rule *rule;
2486 int cur_arg;
2487 int type = REDIRECT_TYPE_NONE;
2488 int code = 302;
2489 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002490 char *cookie = NULL;
2491 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002492 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002493
Cyril Bonté99ed3272010-01-24 23:29:44 +01002494 if (curproxy == &defproxy) {
2495 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
2498 }
2499
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002500 cur_arg = 1;
2501 while (*(args[cur_arg])) {
2502 if (!strcmp(args[cur_arg], "location")) {
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_LOCATION;
2511 cur_arg++;
2512 destination = args[cur_arg];
2513 }
2514 else if (!strcmp(args[cur_arg], "prefix")) {
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 Tarreaub463dfb2008-06-07 23:08:56 +02002520 }
2521
2522 type = REDIRECT_TYPE_PREFIX;
2523 cur_arg++;
2524 destination = args[cur_arg];
2525 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002526 else if (!strcmp(args[cur_arg], "set-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 = 1;
2537 }
2538 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2539 if (!*args[cur_arg + 1]) {
2540 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2541 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002544 }
2545
2546 cur_arg++;
2547 cookie = args[cur_arg];
2548 cookie_set = 0;
2549 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002550 else if (!strcmp(args[cur_arg],"code")) {
2551 if (!*args[cur_arg + 1]) {
2552 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2553 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002556 }
2557 cur_arg++;
2558 code = atol(args[cur_arg]);
2559 if (code < 301 || code > 303) {
2560 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2561 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002564 }
2565 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002566 else if (!strcmp(args[cur_arg],"drop-query")) {
2567 flags |= REDIRECT_FLAG_DROP_QS;
2568 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002569 else if (!strcmp(args[cur_arg],"append-slash")) {
2570 flags |= REDIRECT_FLAG_APPEND_SLASH;
2571 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002572 else if (strcmp(args[cur_arg], "if") == 0 ||
2573 strcmp(args[cur_arg], "unless") == 0) {
2574 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2575 if (!cond) {
2576 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2577 file, linenum, args[0]);
2578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
2580 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002581 break;
2582 }
2583 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002584 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 +02002585 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 }
2589 cur_arg++;
2590 }
2591
2592 if (type == REDIRECT_TYPE_NONE) {
2593 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002597 }
2598
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002599 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2600 rule->cond = cond;
2601 rule->rdr_str = strdup(destination);
2602 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002603 if (cookie) {
2604 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002605 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 */
2607 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002608 if (cookie_set) {
2609 rule->cookie_str = malloc(rule->cookie_len + 10);
2610 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2611 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2612 rule->cookie_len += 9;
2613 } else {
2614 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002615 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002616 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2617 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002618 }
2619 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002620 rule->type = type;
2621 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002622 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002623 LIST_INIT(&rule->list);
2624 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002625 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2626 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002627 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002628 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002629 struct switching_rule *rule;
2630
Willy Tarreaub099aca2008-10-12 17:26:37 +02002631 if (curproxy == &defproxy) {
2632 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002633 err_code |= ERR_ALERT | ERR_FATAL;
2634 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002635 }
2636
Willy Tarreau55ea7572007-06-17 19:56:27 +02002637 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002639
2640 if (*(args[1]) == 0) {
2641 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002644 }
2645
Willy Tarreauef6494c2010-01-28 17:12:36 +01002646 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002647 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2648 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002649 err_code |= ERR_ALERT | ERR_FATAL;
2650 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002651 }
2652
Willy Tarreauef6494c2010-01-28 17:12:36 +01002653 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002654 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002655 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 }
2659
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002660 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002661
Willy Tarreau55ea7572007-06-17 19:56:27 +02002662 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2663 rule->cond = cond;
2664 rule->be.name = strdup(args[1]);
2665 LIST_INIT(&rule->list);
2666 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2667 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002668 else if ((!strcmp(args[0], "force-persist")) ||
2669 (!strcmp(args[0], "ignore-persist"))) {
2670 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002671
2672 if (curproxy == &defproxy) {
2673 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677
2678 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2679 err_code |= ERR_WARN;
2680
Willy Tarreauef6494c2010-01-28 17:12:36 +01002681 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002682 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2683 file, linenum, args[0]);
2684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
2686 }
2687
Willy Tarreauef6494c2010-01-28 17:12:36 +01002688 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002689 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2690 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002695 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002696
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002697 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002698 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002699 if (!strcmp(args[0], "force-persist")) {
2700 rule->type = PERSIST_TYPE_FORCE;
2701 } else {
2702 rule->type = PERSIST_TYPE_IGNORE;
2703 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002705 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002706 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002707 else if (!strcmp(args[0], "stick-table")) {
2708 int myidx = 1;
2709
Emeric Brun32da3c42010-09-23 18:39:19 +02002710 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002711 curproxy->table.type = (unsigned int)-1;
2712 while (*args[myidx]) {
2713 const char *err;
2714
2715 if (strcmp(args[myidx], "size") == 0) {
2716 myidx++;
2717 if (!*(args[myidx])) {
2718 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2719 file, linenum, args[myidx-1]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2724 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2725 file, linenum, *err, args[myidx-1]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002729 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002730 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002731 else if (strcmp(args[myidx], "peers") == 0) {
2732 myidx++;
2733 if (!*(args[myidx])) {
2734 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2735 file, linenum, args[myidx-1]);
2736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
2738 }
2739 curproxy->table.peers.name = strdup(args[myidx++]);
2740 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002741 else if (strcmp(args[myidx], "expire") == 0) {
2742 myidx++;
2743 if (!*(args[myidx])) {
2744 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2745 file, linenum, args[myidx-1]);
2746 err_code |= ERR_ALERT | ERR_FATAL;
2747 goto out;
2748 }
2749 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2750 if (err) {
2751 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2752 file, linenum, *err, args[myidx-1]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
2756 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002757 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002758 }
2759 else if (strcmp(args[myidx], "nopurge") == 0) {
2760 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002761 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002762 }
2763 else if (strcmp(args[myidx], "type") == 0) {
2764 myidx++;
2765 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2766 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2767 file, linenum, args[myidx]);
2768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
2770 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002771 /* myidx already points to next arg */
2772 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002773 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002774 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002775 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002776
2777 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002778 nw = args[myidx];
2779 while (*nw) {
2780 /* the "store" keyword supports a comma-separated list */
2781 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002782 sa = NULL; /* store arg */
2783 while (*nw && *nw != ',') {
2784 if (*nw == '(') {
2785 *nw = 0;
2786 sa = ++nw;
2787 while (*nw != ')') {
2788 if (!*nw) {
2789 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2790 file, linenum, args[0], cw);
2791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
2793 }
2794 nw++;
2795 }
2796 *nw = '\0';
2797 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002798 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002799 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002800 if (*nw)
2801 *nw++ = '\0';
2802 type = stktable_get_data_type(cw);
2803 if (type < 0) {
2804 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2805 file, linenum, args[0], cw);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
Willy Tarreauac782882010-06-20 10:41:54 +02002809
2810 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2811 switch (err) {
2812 case PE_NONE: break;
2813 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002814 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2815 file, linenum, args[0], cw);
2816 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002817 break;
2818
2819 case PE_ARG_MISSING:
2820 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2821 file, linenum, args[0], cw);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
2824
2825 case PE_ARG_NOT_USED:
2826 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830
2831 default:
2832 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2833 file, linenum, args[0], cw);
2834 err_code |= ERR_ALERT | ERR_FATAL;
2835 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002836 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002837 }
2838 myidx++;
2839 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002840 else {
2841 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2842 file, linenum, args[myidx]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002845 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 }
2847
2848 if (!curproxy->table.size) {
2849 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2850 file, linenum);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
2854
2855 if (curproxy->table.type == (unsigned int)-1) {
2856 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2857 file, linenum);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861 }
2862 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 struct sticking_rule *rule;
2864 struct pattern_expr *expr;
2865 int myidx = 0;
2866 const char *name = NULL;
2867 int flags;
2868
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2876 err_code |= ERR_WARN;
2877 goto out;
2878 }
2879
2880 myidx++;
2881 if ((strcmp(args[myidx], "store") == 0) ||
2882 (strcmp(args[myidx], "store-request") == 0)) {
2883 myidx++;
2884 flags = STK_IS_STORE;
2885 }
2886 else if (strcmp(args[myidx], "store-response") == 0) {
2887 myidx++;
2888 flags = STK_IS_STORE | STK_ON_RSP;
2889 }
2890 else if (strcmp(args[myidx], "match") == 0) {
2891 myidx++;
2892 flags = STK_IS_MATCH;
2893 }
2894 else if (strcmp(args[myidx], "on") == 0) {
2895 myidx++;
2896 flags = STK_IS_MATCH | STK_IS_STORE;
2897 }
2898 else {
2899 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902 }
2903
2904 if (*(args[myidx]) == 0) {
2905 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
2908 }
2909
Emeric Brun485479d2010-09-23 18:02:19 +02002910 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002912 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (flags & STK_ON_RSP) {
2918 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2919 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2920 file, linenum, args[0], expr->fetch->kw);
2921 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002922 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 goto out;
2924 }
2925 } else {
2926 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2927 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2928 file, linenum, args[0], expr->fetch->kw);
2929 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002930 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002931 goto out;
2932 }
2933 }
2934
2935 if (strcmp(args[myidx], "table") == 0) {
2936 myidx++;
2937 name = args[myidx++];
2938 }
2939
Willy Tarreauef6494c2010-01-28 17:12:36 +01002940 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2941 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002942 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2943 file, linenum, args[0]);
2944 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002945 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002946 goto out;
2947 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002948 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002949 else if (*(args[myidx])) {
2950 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2951 file, linenum, args[0], args[myidx]);
2952 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002953 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002954 goto out;
2955 }
Emeric Brun97679e72010-09-23 17:56:44 +02002956 if (flags & STK_ON_RSP)
2957 err_code |= warnif_cond_requires_req(cond, file, linenum);
2958 else
2959 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002960
Emeric Brunb982a3d2010-01-04 15:45:53 +01002961 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2962 rule->cond = cond;
2963 rule->expr = expr;
2964 rule->flags = flags;
2965 rule->table.name = name ? strdup(name) : NULL;
2966 LIST_INIT(&rule->list);
2967 if (flags & STK_ON_RSP)
2968 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2969 else
2970 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2971 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002972 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002975
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2977 curproxy->uri_auth = NULL; /* we must detach from the default config */
2978
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002979 if (!*args[1]) {
2980 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002981 } else if (!strcmp(args[1], "admin")) {
2982 struct stats_admin_rule *rule;
2983
2984 if (curproxy == &defproxy) {
2985 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989
2990 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2991 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2992 err_code |= ERR_ALERT | ERR_ABORT;
2993 goto out;
2994 }
2995
2996 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2997 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2998 file, linenum, args[0], args[1]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3003 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3004 file, linenum, args[0], args[1]);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008
3009 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3010
3011 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3012 rule->cond = cond;
3013 LIST_INIT(&rule->list);
3014 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 } else if (!strcmp(args[1], "uri")) {
3016 if (*(args[2]) == 0) {
3017 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3021 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_ABORT;
3023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 }
3025 } else if (!strcmp(args[1], "realm")) {
3026 if (*(args[2]) == 0) {
3027 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003030 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3031 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003032 err_code |= ERR_ALERT | ERR_ABORT;
3033 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003035 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003036 unsigned interval;
3037
3038 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3039 if (err) {
3040 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3041 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003044 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3045 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_ABORT;
3047 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003048 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003049 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003050 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003051
3052 if (curproxy == &defproxy) {
3053 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
3056 }
3057
3058 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3059 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3060 err_code |= ERR_ALERT | ERR_ABORT;
3061 goto out;
3062 }
3063
Willy Tarreauff011f22011-01-06 17:51:27 +01003064 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3065 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003066 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3067 file, linenum, args[0]);
3068 err_code |= ERR_WARN;
3069 }
3070
Willy Tarreauff011f22011-01-06 17:51:27 +01003071 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003072
Willy Tarreauff011f22011-01-06 17:51:27 +01003073 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003074 err_code |= ERR_ALERT | ERR_ABORT;
3075 goto out;
3076 }
3077
Willy Tarreauff011f22011-01-06 17:51:27 +01003078 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3079 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003080
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 } else if (!strcmp(args[1], "auth")) {
3082 if (*(args[2]) == 0) {
3083 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_FATAL;
3085 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3087 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_ABORT;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 }
3091 } else if (!strcmp(args[1], "scope")) {
3092 if (*(args[2]) == 0) {
3093 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
3101 } else if (!strcmp(args[1], "enable")) {
3102 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3103 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_ABORT;
3105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003106 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003107 } else if (!strcmp(args[1], "hide-version")) {
3108 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_ABORT;
3111 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003112 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003113 } else if (!strcmp(args[1], "show-legends")) {
3114 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3115 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3116 err_code |= ERR_ALERT | ERR_ABORT;
3117 goto out;
3118 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003119 } else if (!strcmp(args[1], "show-node")) {
3120
3121 if (*args[2]) {
3122 int i;
3123 char c;
3124
3125 for (i=0; args[2][i]; i++) {
3126 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003127 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3128 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003129 break;
3130 }
3131
3132 if (!i || args[2][i]) {
3133 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3134 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3135 file, linenum, args[0], args[1]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139 }
3140
3141 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
3145 }
3146 } else if (!strcmp(args[1], "show-desc")) {
3147 char *desc = NULL;
3148
3149 if (*args[2]) {
3150 int i, len=0;
3151 char *d;
3152
3153 for(i=2; *args[i]; i++)
3154 len += strlen(args[i])+1;
3155
3156 desc = d = (char *)calloc(1, len);
3157
3158 d += sprintf(d, "%s", args[2]);
3159 for(i=3; *args[i]; i++)
3160 d += sprintf(d, " %s", args[i]);
3161 }
3162
3163 if (!*args[2] && !global.desc)
3164 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3165 file, linenum, args[1]);
3166 else {
3167 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3168 free(desc);
3169 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3170 err_code |= ERR_ALERT | ERR_ABORT;
3171 goto out;
3172 }
3173 free(desc);
3174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003176stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003177 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 +01003178 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003179 err_code |= ERR_ALERT | ERR_FATAL;
3180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 }
3182 }
3183 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003184 int optnum;
3185
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003186 if (*(args[1]) == '\0') {
3187 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3188 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003192
3193 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3194 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003195 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3196 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3197 file, linenum, cfg_opts[optnum].name);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
Willy Tarreau93893792009-07-23 13:19:11 +02003201 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3202 err_code |= ERR_WARN;
3203 goto out;
3204 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003205
Willy Tarreau3842f002009-06-14 11:39:52 +02003206 curproxy->no_options &= ~cfg_opts[optnum].val;
3207 curproxy->options &= ~cfg_opts[optnum].val;
3208
3209 switch (kwm) {
3210 case KWM_STD:
3211 curproxy->options |= cfg_opts[optnum].val;
3212 break;
3213 case KWM_NO:
3214 curproxy->no_options |= cfg_opts[optnum].val;
3215 break;
3216 case KWM_DEF: /* already cleared */
3217 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003218 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003219
Willy Tarreau93893792009-07-23 13:19:11 +02003220 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003221 }
3222 }
3223
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003224 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3225 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003226 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3227 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3228 file, linenum, cfg_opts2[optnum].name);
3229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
3231 }
Willy Tarreau93893792009-07-23 13:19:11 +02003232 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3233 err_code |= ERR_WARN;
3234 goto out;
3235 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003236
Willy Tarreau3842f002009-06-14 11:39:52 +02003237 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3238 curproxy->options2 &= ~cfg_opts2[optnum].val;
3239
3240 switch (kwm) {
3241 case KWM_STD:
3242 curproxy->options2 |= cfg_opts2[optnum].val;
3243 break;
3244 case KWM_NO:
3245 curproxy->no_options2 |= cfg_opts2[optnum].val;
3246 break;
3247 case KWM_DEF: /* already cleared */
3248 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003249 }
Willy Tarreau93893792009-07-23 13:19:11 +02003250 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003251 }
3252 }
3253
Willy Tarreau3842f002009-06-14 11:39:52 +02003254 if (kwm != KWM_STD) {
3255 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003256 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003259 }
3260
Emeric Brun3a058f32009-06-30 18:26:00 +02003261 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003262 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003263 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003265 if (*(args[2]) != '\0') {
3266 if (!strcmp(args[2], "clf")) {
3267 curproxy->options2 |= PR_O2_CLFLOG;
3268 } else {
3269 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003272 }
3273 }
3274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 else if (!strcmp(args[1], "tcplog"))
3276 /* generate a detailed TCP log */
3277 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 else if (!strcmp(args[1], "tcpka")) {
3279 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003280 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003281 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003282
3283 if (curproxy->cap & PR_CAP_FE)
3284 curproxy->options |= PR_O_TCP_CLI_KA;
3285 if (curproxy->cap & PR_CAP_BE)
3286 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 }
3288 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003289 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_WARN;
3291
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003293 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003294 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003295 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003296 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003297 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003298 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003299 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003300 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 if (!*args[2]) { /* no argument */
3302 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3303 curproxy->check_len = strlen(DEF_CHECK_REQ);
3304 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003305 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 curproxy->check_req = (char *)malloc(reqlen);
3307 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003308 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003310 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 if (*args[4])
3312 reqlen += strlen(args[4]);
3313 else
3314 reqlen += strlen("HTTP/1.0");
3315
3316 curproxy->check_req = (char *)malloc(reqlen);
3317 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003318 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003320 }
3321 else if (!strcmp(args[1], "ssl-hello-chk")) {
3322 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003323 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003325
Willy Tarreaua534fea2008-08-03 12:19:50 +02003326 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003327 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003328 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003329 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003330 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003331 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003332 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003333 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
Willy Tarreau23677902007-05-08 23:50:35 +02003335 else if (!strcmp(args[1], "smtpchk")) {
3336 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003337 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003338 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003339 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003340 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003341 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003342 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003343 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003344 curproxy->options |= PR_O_SMTP_CHK;
3345
3346 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3347 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3348 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3349 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3350 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3351 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3352 curproxy->check_req = (char *)malloc(reqlen);
3353 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3354 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3355 } else {
3356 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3357 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3358 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3359 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3360 }
3361 }
3362 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003363 else if (!strcmp(args[1], "pgsql-check")) {
3364 /* use PostgreSQL request to check servers' health */
3365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3366 err_code |= ERR_WARN;
3367
3368 free(curproxy->check_req);
3369 curproxy->check_req = NULL;
3370 curproxy->options &= ~PR_O_HTTP_CHK;
3371 curproxy->options &= ~PR_O_SMTP_CHK;
3372 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3373 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3374 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3375 curproxy->options2 |= PR_O2_PGSQL_CHK;
3376
3377 if (*(args[2])) {
3378 int cur_arg = 2;
3379
3380 while (*(args[cur_arg])) {
3381 if (strcmp(args[cur_arg], "user") == 0) {
3382 char * packet;
3383 uint32_t packet_len;
3384 uint32_t pv;
3385
3386 /* suboption header - needs additional argument for it */
3387 if (*(args[cur_arg+1]) == 0) {
3388 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3389 file, linenum, args[0], args[1], args[cur_arg]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393
3394 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3395 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3396 pv = htonl(0x30000); /* protocol version 3.0 */
3397
3398 packet = (char*) calloc(1, packet_len);
3399
3400 memcpy(packet + 4, &pv, 4);
3401
3402 /* copy "user" */
3403 memcpy(packet + 8, "user", 4);
3404
3405 /* copy username */
3406 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3407
3408 free(curproxy->check_req);
3409 curproxy->check_req = packet;
3410 curproxy->check_len = packet_len;
3411
3412 packet_len = htonl(packet_len);
3413 memcpy(packet, &packet_len, 4);
3414 cur_arg += 2;
3415 } else {
3416 /* unknown suboption - catchall */
3417 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3418 file, linenum, args[0], args[1]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422 } /* end while loop */
3423 }
3424 }
3425
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003426 else if (!strcmp(args[1], "mysql-check")) {
3427 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003428 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3429 err_code |= ERR_WARN;
3430
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003431 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003432 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003433 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003434 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003435 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003436 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003437 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003438 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003439
3440 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3441 * const char mysql40_client_auth_pkt[] = {
3442 * "\x0e\x00\x00" // packet length
3443 * "\x01" // packet number
3444 * "\x00\x00" // client capabilities
3445 * "\x00\x00\x01" // max packet
3446 * "haproxy\x00" // username (null terminated string)
3447 * "\x00" // filler (always 0x00)
3448 * "\x01\x00\x00" // packet length
3449 * "\x00" // packet number
3450 * "\x01" // COM_QUIT command
3451 * };
3452 */
3453
3454 if (*(args[2])) {
3455 int cur_arg = 2;
3456
3457 while (*(args[cur_arg])) {
3458 if (strcmp(args[cur_arg], "user") == 0) {
3459 char *mysqluser;
3460 int packetlen, reqlen, userlen;
3461
3462 /* suboption header - needs additional argument for it */
3463 if (*(args[cur_arg+1]) == 0) {
3464 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3465 file, linenum, args[0], args[1], args[cur_arg]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469 mysqluser = args[cur_arg + 1];
3470 userlen = strlen(mysqluser);
3471 packetlen = userlen + 7;
3472 reqlen = packetlen + 9;
3473
3474 free(curproxy->check_req);
3475 curproxy->check_req = (char *)calloc(1, reqlen);
3476 curproxy->check_len = reqlen;
3477
3478 snprintf(curproxy->check_req, 4, "%c%c%c",
3479 ((unsigned char) packetlen & 0xff),
3480 ((unsigned char) (packetlen >> 8) & 0xff),
3481 ((unsigned char) (packetlen >> 16) & 0xff));
3482
3483 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003484 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003485 curproxy->check_req[8] = 1;
3486 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3487 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3488 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3489 cur_arg += 2;
3490 } else {
3491 /* unknown suboption - catchall */
3492 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3493 file, linenum, args[0], args[1]);
3494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
3496 }
3497 } /* end while loop */
3498 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003499 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003500 else if (!strcmp(args[1], "ldap-check")) {
3501 /* use LDAP request to check servers' health */
3502 free(curproxy->check_req);
3503 curproxy->check_req = NULL;
3504 curproxy->options &= ~PR_O_HTTP_CHK;
3505 curproxy->options &= ~PR_O_SMTP_CHK;
3506 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3507 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003508 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003509 curproxy->options2 |= PR_O2_LDAP_CHK;
3510
3511 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3512 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3513 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3514 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003515 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003516 int cur_arg;
3517
3518 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3519 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003520 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003521
3522 curproxy->options |= PR_O_FWDFOR;
3523
3524 free(curproxy->fwdfor_hdr_name);
3525 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3526 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3527
3528 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3529 cur_arg = 2;
3530 while (*(args[cur_arg])) {
3531 if (!strcmp(args[cur_arg], "except")) {
3532 /* suboption except - needs additional argument for it */
3533 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3534 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3535 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003538 }
3539 /* flush useless bits */
3540 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003541 cur_arg += 2;
3542 } else if (!strcmp(args[cur_arg], "header")) {
3543 /* suboption header - needs additional argument for it */
3544 if (*(args[cur_arg+1]) == 0) {
3545 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3546 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003549 }
3550 free(curproxy->fwdfor_hdr_name);
3551 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3552 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3553 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003554 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003555 /* unknown suboption - catchall */
3556 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3557 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003560 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003561 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003562 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003563 else if (!strcmp(args[1], "originalto")) {
3564 int cur_arg;
3565
3566 /* insert x-original-to field, but not for the IP address listed as an except.
3567 * set default options (ie: bitfield, header name, etc)
3568 */
3569
3570 curproxy->options |= PR_O_ORGTO;
3571
3572 free(curproxy->orgto_hdr_name);
3573 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3574 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3575
3576 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3577 cur_arg = 2;
3578 while (*(args[cur_arg])) {
3579 if (!strcmp(args[cur_arg], "except")) {
3580 /* suboption except - needs additional argument for it */
3581 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3582 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3583 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003586 }
3587 /* flush useless bits */
3588 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3589 cur_arg += 2;
3590 } else if (!strcmp(args[cur_arg], "header")) {
3591 /* suboption header - needs additional argument for it */
3592 if (*(args[cur_arg+1]) == 0) {
3593 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3594 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_FATAL;
3596 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003597 }
3598 free(curproxy->orgto_hdr_name);
3599 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3600 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3601 cur_arg += 2;
3602 } else {
3603 /* unknown suboption - catchall */
3604 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3605 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003608 }
3609 } /* end while loop */
3610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 else {
3612 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003615 }
Willy Tarreau93893792009-07-23 13:19:11 +02003616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003618 else if (!strcmp(args[0], "default_backend")) {
3619 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003621
3622 if (*(args[1]) == 0) {
3623 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003626 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003627 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003628 curproxy->defbe.name = strdup(args[1]);
3629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003633
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003634 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 /* enable reconnections to dispatch */
3638 curproxy->options |= PR_O_REDISP;
3639 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003640 else if (!strcmp(args[0], "http-check")) {
3641 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003643
3644 if (strcmp(args[1], "disable-on-404") == 0) {
3645 /* enable a graceful server shutdown on an HTTP 404 response */
3646 curproxy->options |= PR_O_DISABLE404;
3647 }
Willy Tarreauef781042010-01-27 11:53:01 +01003648 else if (strcmp(args[1], "send-state") == 0) {
3649 /* enable emission of the apparent state of a server in HTTP checks */
3650 curproxy->options2 |= PR_O2_CHK_SNDST;
3651 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003652 else if (strcmp(args[1], "expect") == 0) {
3653 const char *ptr_arg;
3654 int cur_arg;
3655
3656 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3657 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
3660 }
3661
3662 cur_arg = 2;
3663 /* consider exclamation marks, sole or at the beginning of a word */
3664 while (*(ptr_arg = args[cur_arg])) {
3665 while (*ptr_arg == '!') {
3666 curproxy->options2 ^= PR_O2_EXP_INV;
3667 ptr_arg++;
3668 }
3669 if (*ptr_arg)
3670 break;
3671 cur_arg++;
3672 }
3673 /* now ptr_arg points to the beginning of a word past any possible
3674 * exclamation mark, and cur_arg is the argument which holds this word.
3675 */
3676 if (strcmp(ptr_arg, "status") == 0) {
3677 if (!*(args[cur_arg + 1])) {
3678 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3679 file, linenum, args[0], args[1], ptr_arg);
3680 err_code |= ERR_ALERT | ERR_FATAL;
3681 goto out;
3682 }
3683 curproxy->options2 |= PR_O2_EXP_STS;
3684 curproxy->expect_str = strdup(args[cur_arg + 1]);
3685 }
3686 else if (strcmp(ptr_arg, "string") == 0) {
3687 if (!*(args[cur_arg + 1])) {
3688 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3689 file, linenum, args[0], args[1], ptr_arg);
3690 err_code |= ERR_ALERT | ERR_FATAL;
3691 goto out;
3692 }
3693 curproxy->options2 |= PR_O2_EXP_STR;
3694 curproxy->expect_str = strdup(args[cur_arg + 1]);
3695 }
3696 else if (strcmp(ptr_arg, "rstatus") == 0) {
3697 if (!*(args[cur_arg + 1])) {
3698 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3699 file, linenum, args[0], args[1], ptr_arg);
3700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
3702 }
3703 curproxy->options2 |= PR_O2_EXP_RSTS;
3704 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3705 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3706 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3707 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3708 err_code |= ERR_ALERT | ERR_FATAL;
3709 goto out;
3710 }
3711 }
3712 else if (strcmp(ptr_arg, "rstring") == 0) {
3713 if (!*(args[cur_arg + 1])) {
3714 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3715 file, linenum, args[0], args[1], ptr_arg);
3716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
3718 }
3719 curproxy->options2 |= PR_O2_EXP_RSTR;
3720 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3721 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3722 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3723 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727 }
3728 else {
3729 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3730 file, linenum, args[0], args[1], ptr_arg);
3731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
3733 }
3734 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003735 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003736 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003739 }
3740 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003741 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003742 if (curproxy == &defproxy) {
3743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003746 }
3747
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003750
3751 if (strcmp(args[1], "fail") == 0) {
3752 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003753 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003754 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3755 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003758 }
3759
Willy Tarreauef6494c2010-01-28 17:12:36 +01003760 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003761 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3762 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003765 }
3766 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3767 }
3768 else {
3769 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003772 }
3773 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774#ifdef TPROXY
3775 else if (!strcmp(args[0], "transparent")) {
3776 /* enable transparent proxy connections */
3777 curproxy->options |= PR_O_TRANSP;
3778 }
3779#endif
3780 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003781 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003783
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 if (*(args[1]) == 0) {
3785 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789 curproxy->maxconn = atol(args[1]);
3790 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003791 else if (!strcmp(args[0], "backlog")) { /* backlog */
3792 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003794
3795 if (*(args[1]) == 0) {
3796 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003799 }
3800 curproxy->backlog = atol(args[1]);
3801 }
Willy Tarreau86034312006-12-29 00:10:33 +01003802 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003803 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003805
Willy Tarreau86034312006-12-29 00:10:33 +01003806 if (*(args[1]) == 0) {
3807 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003810 }
3811 curproxy->fullconn = atol(args[1]);
3812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3814 if (*(args[1]) == 0) {
3815 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003819 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3820 if (err) {
3821 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3822 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003825 }
3826 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
3828 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003829 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003835 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 if (strchr(args[1], ':') == NULL) {
3839 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003843 sk = str2sa(args[1]);
3844 if (!sk) {
3845 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
3848 }
3849 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003850 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003855
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003856 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003857 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3858 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003863 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3865 err_code |= ERR_WARN;
3866
3867 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3868 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3869 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3870 }
3871 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3872 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3873 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3874 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003875 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3876 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3877 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3878 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003879 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003880 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003885 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003887 char *rport, *raddr;
3888 short realport = 0;
3889 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003891 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003896 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898
3899 if (!*args[2]) {
3900 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
3903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003905
3906 err = invalid_char(args[1]);
3907 if (err) {
3908 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3909 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003912 }
3913
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003915 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003916
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003917 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3918 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3919 err_code |= ERR_ALERT | ERR_ABORT;
3920 goto out;
3921 }
3922
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003923 /* the servers are linked backwards first */
3924 newsrv->next = curproxy->srv;
3925 curproxy->srv = newsrv;
3926 newsrv->proxy = curproxy;
3927 newsrv->conf.file = file;
3928 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929
Simon Hormanaf514952011-06-21 14:34:57 +09003930 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931 LIST_INIT(&newsrv->pendconns);
3932 do_check = 0;
3933 newsrv->state = SRV_RUNNING; /* early server setup */
3934 newsrv->last_change = now.tv_sec;
3935 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003936
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003937 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003938 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003939 * - IP: => port=+0, relative
3940 * - IP:N => port=N, absolute
3941 * - IP:+N => port=+N, relative
3942 * - IP:-N => port=-N, relative
3943 */
3944 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003945 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003946 if (rport) {
3947 *rport++ = 0;
3948 realport = atol(rport);
3949 if (!isdigit((unsigned char)*rport))
3950 newsrv->state |= SRV_MAPPORTS;
3951 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003953
Willy Tarreaufab5a432011-03-04 15:31:53 +01003954 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003955 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003956 if (!sk) {
3957 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
3960 }
3961 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003962
3963 switch (newsrv->addr.ss_family) {
3964 case AF_INET:
3965 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3966 break;
3967 case AF_INET6:
3968 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3969 break;
3970 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971
3972 newsrv->check_port = curproxy->defsrv.check_port;
3973 newsrv->inter = curproxy->defsrv.inter;
3974 newsrv->fastinter = curproxy->defsrv.fastinter;
3975 newsrv->downinter = curproxy->defsrv.downinter;
3976 newsrv->rise = curproxy->defsrv.rise;
3977 newsrv->fall = curproxy->defsrv.fall;
3978 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3979 newsrv->minconn = curproxy->defsrv.minconn;
3980 newsrv->maxconn = curproxy->defsrv.maxconn;
3981 newsrv->slowstart = curproxy->defsrv.slowstart;
3982 newsrv->onerror = curproxy->defsrv.onerror;
3983 newsrv->consecutive_errors_limit
3984 = curproxy->defsrv.consecutive_errors_limit;
3985 newsrv->uweight = newsrv->iweight
3986 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003988 newsrv->curfd = -1; /* no health-check in progress */
3989 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003991 cur_arg = 3;
3992 } else {
3993 newsrv = &curproxy->defsrv;
3994 cur_arg = 1;
3995 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003996
Willy Tarreaubaaee002006-06-26 02:48:02 +02003997 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003998 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003999 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004000
4001 if (!*args[cur_arg + 1]) {
4002 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4003 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004004 err_code |= ERR_ALERT | ERR_FATAL;
4005 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004006 }
4007
4008 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004009 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004010
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004011 if (newsrv->puid <= 0) {
4012 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004013 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004016 }
4017
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004018 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4019 if (node) {
4020 struct server *target = container_of(node, struct server, conf.id);
4021 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4022 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004027 cur_arg += 2;
4028 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 newsrv->cookie = strdup(args[cur_arg + 1]);
4031 newsrv->cklen = strlen(args[cur_arg + 1]);
4032 cur_arg += 2;
4033 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004034 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004035 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4036 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4037 cur_arg += 2;
4038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004040 if (!*args[cur_arg + 1]) {
4041 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4042 file, linenum, args[cur_arg]);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045 }
4046
Willy Tarreaubaaee002006-06-26 02:48:02 +02004047 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004048 if (newsrv->rise <= 0) {
4049 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4050 file, linenum, args[cur_arg]);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054
Willy Tarreau96839092010-03-29 10:02:24 +02004055 if (newsrv->health)
4056 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004057 cur_arg += 2;
4058 }
4059 else if (!strcmp(args[cur_arg], "fall")) {
4060 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004061
4062 if (!*args[cur_arg + 1]) {
4063 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4064 file, linenum, args[cur_arg]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068
4069 if (newsrv->fall <= 0) {
4070 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4071 file, linenum, args[cur_arg]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 cur_arg += 2;
4077 }
4078 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004079 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4080 if (err) {
4081 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4082 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004085 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004086 if (val <= 0) {
4087 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4088 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004091 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004092 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004093 cur_arg += 2;
4094 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004095 else if (!strcmp(args[cur_arg], "fastinter")) {
4096 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4097 if (err) {
4098 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4099 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004103 if (val <= 0) {
4104 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4105 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004108 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004109 newsrv->fastinter = val;
4110 cur_arg += 2;
4111 }
4112 else if (!strcmp(args[cur_arg], "downinter")) {
4113 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4114 if (err) {
4115 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4116 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004120 if (val <= 0) {
4121 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4122 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004125 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004126 newsrv->downinter = val;
4127 cur_arg += 2;
4128 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004129 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004130 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004131 if (!sk) {
4132 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004137 cur_arg += 2;
4138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 else if (!strcmp(args[cur_arg], "port")) {
4140 newsrv->check_port = atol(args[cur_arg + 1]);
4141 cur_arg += 2;
4142 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004143 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 newsrv->state |= SRV_BACKUP;
4145 cur_arg ++;
4146 }
Simon Hormanfa461682011-06-25 09:39:49 +09004147 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4148 newsrv->state |= SRV_NON_STICK;
4149 cur_arg ++;
4150 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004151 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4152 newsrv->state |= SRV_SEND_PROXY;
4153 cur_arg ++;
4154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004155 else if (!strcmp(args[cur_arg], "weight")) {
4156 int w;
4157 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004158 if (w < 0 || w > 256) {
4159 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004163 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004164 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 cur_arg += 2;
4166 }
4167 else if (!strcmp(args[cur_arg], "minconn")) {
4168 newsrv->minconn = atol(args[cur_arg + 1]);
4169 cur_arg += 2;
4170 }
4171 else if (!strcmp(args[cur_arg], "maxconn")) {
4172 newsrv->maxconn = atol(args[cur_arg + 1]);
4173 cur_arg += 2;
4174 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004175 else if (!strcmp(args[cur_arg], "maxqueue")) {
4176 newsrv->maxqueue = atol(args[cur_arg + 1]);
4177 cur_arg += 2;
4178 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004179 else if (!strcmp(args[cur_arg], "slowstart")) {
4180 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004181 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004182 if (err) {
4183 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4184 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004187 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004188 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004189 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4190 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004193 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004194 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004195 cur_arg += 2;
4196 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004197 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004198
4199 if (!*args[cur_arg + 1]) {
4200 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004204 }
4205
4206 newsrv->trackit = strdup(args[cur_arg + 1]);
4207
4208 cur_arg += 2;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 global.maxsock++;
4212 do_check = 1;
4213 cur_arg += 1;
4214 }
Willy Tarreau96839092010-03-29 10:02:24 +02004215 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4216 newsrv->state |= SRV_MAINTAIN;
4217 newsrv->state &= ~SRV_RUNNING;
4218 newsrv->health = 0;
4219 cur_arg += 1;
4220 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004221 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004222 if (!strcmp(args[cur_arg + 1], "none"))
4223 newsrv->observe = HANA_OBS_NONE;
4224 else if (!strcmp(args[cur_arg + 1], "layer4"))
4225 newsrv->observe = HANA_OBS_LAYER4;
4226 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4227 if (curproxy->mode != PR_MODE_HTTP) {
4228 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4229 file, linenum, args[cur_arg + 1]);
4230 err_code |= ERR_ALERT;
4231 }
4232 newsrv->observe = HANA_OBS_LAYER7;
4233 }
4234 else {
4235 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004236 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004237 file, linenum, args[cur_arg], args[cur_arg + 1]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240 }
4241
4242 cur_arg += 2;
4243 }
4244 else if (!strcmp(args[cur_arg], "on-error")) {
4245 if (!strcmp(args[cur_arg + 1], "fastinter"))
4246 newsrv->onerror = HANA_ONERR_FASTINTER;
4247 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4248 newsrv->onerror = HANA_ONERR_FAILCHK;
4249 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4250 newsrv->onerror = HANA_ONERR_SUDDTH;
4251 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4252 newsrv->onerror = HANA_ONERR_MARKDWN;
4253 else {
4254 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004255 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004256 file, linenum, args[cur_arg], args[cur_arg + 1]);
4257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
4259 }
4260
4261 cur_arg += 2;
4262 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004263 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4264 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4265 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4266 else {
4267 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4268 file, linenum, args[cur_arg], args[cur_arg + 1]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
4273 cur_arg += 2;
4274 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004275 else if (!strcmp(args[cur_arg], "error-limit")) {
4276 if (!*args[cur_arg + 1]) {
4277 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4278 file, linenum, args[cur_arg]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
4282
4283 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4284
4285 if (newsrv->consecutive_errors_limit <= 0) {
4286 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4287 file, linenum, args[cur_arg]);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004291 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004292 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004293 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004294 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004295 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004296
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004298#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004299 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004300 file, linenum, "source", "usesrc");
4301#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004302 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004304#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004305 err_code |= ERR_ALERT | ERR_FATAL;
4306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 }
4308 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004309 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4310 if (!sk) {
4311 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
4314 }
4315 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004316
4317 if (port_low != port_high) {
4318 int i;
4319 if (port_low <= 0 || port_low > 65535 ||
4320 port_high <= 0 || port_high > 65535 ||
4321 port_low > port_high) {
4322 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4323 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004326 }
4327 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4328 for (i = 0; i < newsrv->sport_range->size; i++)
4329 newsrv->sport_range->ports[i] = port_low + i;
4330 }
4331
Willy Tarreaubaaee002006-06-26 02:48:02 +02004332 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 while (*(args[cur_arg])) {
4334 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004335#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4336#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4338 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4339 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004342 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004343#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004344 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004345 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004346 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_FATAL;
4348 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004349 }
4350 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004351 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004352 newsrv->state |= SRV_TPROXY_CLI;
4353 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004354 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004355 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004356 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4357 char *name, *end;
4358
4359 name = args[cur_arg+1] + 7;
4360 while (isspace(*name))
4361 name++;
4362
4363 end = name;
4364 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4365 end++;
4366
4367 newsrv->state &= ~SRV_TPROXY_MASK;
4368 newsrv->state |= SRV_TPROXY_DYN;
4369 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4370 newsrv->bind_hdr_len = end - name;
4371 memcpy(newsrv->bind_hdr_name, name, end - name);
4372 newsrv->bind_hdr_name[end-name] = '\0';
4373 newsrv->bind_hdr_occ = -1;
4374
4375 /* now look for an occurrence number */
4376 while (isspace(*end))
4377 end++;
4378 if (*end == ',') {
4379 end++;
4380 name = end;
4381 if (*end == '-')
4382 end++;
4383 while (isdigit(*end))
4384 end++;
4385 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4386 }
4387
4388 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4389 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4390 " occurrences values smaller than %d.\n",
4391 file, linenum, MAX_HDR_HISTORY);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004396 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004397 if (!sk) {
4398 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4399 err_code |= ERR_ALERT | ERR_FATAL;
4400 goto out;
4401 }
4402 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404 }
4405 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004406#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004408#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004409 cur_arg += 2;
4410 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004411#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004412 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004413 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_ALERT | ERR_FATAL;
4415 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4417 } /* "usesrc" */
4418
4419 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4420#ifdef SO_BINDTODEVICE
4421 if (!*args[cur_arg + 1]) {
4422 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4423 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 }
4427 if (newsrv->iface_name)
4428 free(newsrv->iface_name);
4429
4430 newsrv->iface_name = strdup(args[cur_arg + 1]);
4431 newsrv->iface_len = strlen(newsrv->iface_name);
4432 global.last_checks |= LSTCHK_NETADM;
4433#else
4434 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4435 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004438#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004439 cur_arg += 2;
4440 continue;
4441 }
4442 /* this keyword in not an option of "source" */
4443 break;
4444 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004446 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004447 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4448 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004453 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004454 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 +01004455 file, linenum, newsrv->id);
4456 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004457 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 +01004458 file, linenum);
4459
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 }
4463 }
4464
4465 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004466 if (newsrv->trackit) {
4467 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4468 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004471 }
4472
David du Colombier6f5ccb12011-03-10 22:26:24 +01004473 switch (newsrv->check_addr.ss_family) {
4474 case AF_INET:
4475 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4476 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4477 break;
4478 case AF_INET6:
4479 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4480 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4481 break;
4482 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004483
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4485 newsrv->check_port = realport; /* by default */
4486 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004487 /* not yet valid, because no port was set on
4488 * the server either. We'll check if we have
4489 * a known port on the first listener.
4490 */
4491 struct listener *l;
4492 l = curproxy->listen;
4493 if (l) {
4494 int port;
4495 port = (l->addr.ss_family == AF_INET6)
4496 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4497 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4498 newsrv->check_port = port;
4499 }
4500 }
4501 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4503 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004507
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004508 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004509 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004510 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4511 err_code |= ERR_ALERT | ERR_ABORT;
4512 goto out;
4513 }
4514
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004515 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 newsrv->state |= SRV_CHECKED;
4517 }
4518
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004519 if (!defsrv) {
4520 if (newsrv->state & SRV_BACKUP)
4521 curproxy->srv_bck++;
4522 else
4523 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004524
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004525 newsrv->prev_state = newsrv->state;
4526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 }
4528 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004529 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 int facility;
4531
4532 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4533 curproxy->logfac1 = global.logfac1;
4534 curproxy->logsrv1 = global.logsrv1;
4535 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004536 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 curproxy->logfac2 = global.logfac2;
4538 curproxy->logsrv2 = global.logsrv2;
4539 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004540 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 }
4542 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004543 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544
4545 facility = get_log_facility(args[2]);
4546 if (facility < 0) {
4547 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4548 exit(1);
4549 }
4550
4551 level = 7; /* max syslog level = debug */
4552 if (*(args[3])) {
4553 level = get_log_level(args[3]);
4554 if (level < 0) {
4555 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4556 exit(1);
4557 }
4558 }
4559
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004560 minlvl = 0; /* limit syslog level to this level (emerg) */
4561 if (*(args[4])) {
4562 minlvl = get_log_level(args[4]);
4563 if (level < 0) {
4564 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4565 exit(1);
4566 }
4567 }
4568
Robert Tsai81ae1952007-12-05 10:47:29 +01004569 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004570 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004571 if (!sk) {
4572 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004573 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
4576 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004577 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004578 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004579 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004580 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004581 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004585 logsrv.addr = *sk;
4586 if (!get_host_port(&logsrv.addr))
4587 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589
4590 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004591 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 curproxy->logfac1 = facility;
4593 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004594 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004597 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 curproxy->logfac2 = facility;
4599 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004600 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 }
4602 else {
4603 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 }
4607 }
4608 else {
4609 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4610 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 }
4614 }
4615 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004616 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004617 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004618
Willy Tarreau977b8e42006-12-29 14:19:17 +01004619 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004621
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004623 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4624 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004627 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004628
4629 /* we must first clear any optional default setting */
4630 curproxy->options &= ~PR_O_TPXY_MASK;
4631 free(curproxy->iface_name);
4632 curproxy->iface_name = NULL;
4633 curproxy->iface_len = 0;
4634
Willy Tarreaud5191e72010-02-09 20:50:45 +01004635 sk = str2sa(args[1]);
4636 if (!sk) {
4637 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
4640 }
4641 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004643
4644 cur_arg = 2;
4645 while (*(args[cur_arg])) {
4646 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004647#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4648#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004649 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4650 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4651 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004654 }
4655#endif
4656 if (!*args[cur_arg + 1]) {
4657 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4658 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004661 }
4662
4663 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004664 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004665 curproxy->options |= PR_O_TPXY_CLI;
4666 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004667 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004668 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004669 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4670 char *name, *end;
4671
4672 name = args[cur_arg+1] + 7;
4673 while (isspace(*name))
4674 name++;
4675
4676 end = name;
4677 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4678 end++;
4679
4680 curproxy->options &= ~PR_O_TPXY_MASK;
4681 curproxy->options |= PR_O_TPXY_DYN;
4682 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4683 curproxy->bind_hdr_len = end - name;
4684 memcpy(curproxy->bind_hdr_name, name, end - name);
4685 curproxy->bind_hdr_name[end-name] = '\0';
4686 curproxy->bind_hdr_occ = -1;
4687
4688 /* now look for an occurrence number */
4689 while (isspace(*end))
4690 end++;
4691 if (*end == ',') {
4692 end++;
4693 name = end;
4694 if (*end == '-')
4695 end++;
4696 while (isdigit(*end))
4697 end++;
4698 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4699 }
4700
4701 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4702 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4703 " occurrences values smaller than %d.\n",
4704 file, linenum, MAX_HDR_HISTORY);
4705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
4707 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004708 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004709 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004710 if (!sk) {
4711 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4712 err_code |= ERR_ALERT | ERR_FATAL;
4713 goto out;
4714 }
4715 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004717 }
4718 global.last_checks |= LSTCHK_NETADM;
4719#if !defined(CONFIG_HAP_LINUX_TPROXY)
4720 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004721#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004722#else /* no TPROXY support */
4723 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004724 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004727#endif
4728 cur_arg += 2;
4729 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004730 }
4731
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004732 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4733#ifdef SO_BINDTODEVICE
4734 if (!*args[cur_arg + 1]) {
4735 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4736 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004739 }
4740 if (curproxy->iface_name)
4741 free(curproxy->iface_name);
4742
4743 curproxy->iface_name = strdup(args[cur_arg + 1]);
4744 curproxy->iface_len = strlen(curproxy->iface_name);
4745 global.last_checks |= LSTCHK_NETADM;
4746#else
4747 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4748 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004751#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004752 cur_arg += 2;
4753 continue;
4754 }
4755 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4756 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004757 err_code |= ERR_ALERT | ERR_FATAL;
4758 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004761 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4762 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4763 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004768 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774
4775 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4776 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004777 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 }
4781 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4783 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004784 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004785 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
4788 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4790 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004791 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
4795 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4797 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004798 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004799 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004800 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 }
4802 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004803 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4804 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004805 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004809 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4811 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004812 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004814 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004815 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004816 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004817 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4818 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004819 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004821 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004822 }
4823 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4825 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004826 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004827 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004828 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004832 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4833 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837
4838 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4839 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004840 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004841 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
4844 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4846 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004847 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 }
4851 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4853 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004854 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004855 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
4858 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4860 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004861 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004862 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
4865 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004866 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4867 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004868 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004869 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004872 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004873 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4874 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004875 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004877 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004880 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004881
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 if (curproxy == &defproxy) {
4883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004887 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004888 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 if (*(args[1]) == 0) {
4891 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004895
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004896 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4897 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4898 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4899 file, linenum, args[0]);
4900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4904 }
4905 else if (*args[2]) {
4906 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4907 file, linenum, args[0], args[2]);
4908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
4910 }
4911
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004912 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004913 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004914 wl->s = strdup(args[1]);
4915 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004916 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
4918 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004925
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4927 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004928 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
4932 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4934 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004938 }
4939 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4941 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004942 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004943 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
4946 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4955 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004956 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4962 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4969 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004975 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004976
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 if (curproxy == &defproxy) {
4978 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004982 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (*(args[1]) == 0) {
4986 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
4990
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004991 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4992 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4993 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4994 file, linenum, args[0]);
4995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998 err_code |= warnif_cond_requires_req(cond, file, linenum);
4999 }
5000 else if (*args[2]) {
5001 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5002 file, linenum, args[0], args[2]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
5006
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005007 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005008 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005009 wl->s = strdup(args[1]);
5010 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
5012 else if (!strcmp(args[0], "errorloc") ||
5013 !strcmp(args[0], "errorloc302") ||
5014 !strcmp(args[0], "errorloc303")) { /* error location */
5015 int errnum, errlen;
5016 char *err;
5017
Willy Tarreau977b8e42006-12-29 14:19:17 +01005018 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005019 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005020
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005022 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
5026
5027 errnum = atol(args[1]);
5028 if (!strcmp(args[0], "errorloc303")) {
5029 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5030 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5031 } else {
5032 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5033 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5034 }
5035
Willy Tarreau0f772532006-12-23 20:51:41 +01005036 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5037 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005038 chunk_destroy(&curproxy->errmsg[rc]);
5039 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005040 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005043
5044 if (rc >= HTTP_ERR_SIZE) {
5045 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5046 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 free(err);
5048 }
5049 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005050 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5051 int errnum, errlen, fd;
5052 char *err;
5053 struct stat stat;
5054
5055 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005057
5058 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005059 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005062 }
5063
5064 fd = open(args[2], O_RDONLY);
5065 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5066 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5067 file, linenum, args[2], args[1]);
5068 if (fd >= 0)
5069 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005072 }
5073
Willy Tarreau27a674e2009-08-17 07:23:33 +02005074 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005075 errlen = stat.st_size;
5076 } else {
5077 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005078 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005080 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005081 }
5082
5083 err = malloc(errlen); /* malloc() must succeed during parsing */
5084 errnum = read(fd, err, errlen);
5085 if (errnum != errlen) {
5086 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5087 file, linenum, args[2], args[1]);
5088 close(fd);
5089 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_ALERT | ERR_FATAL;
5091 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005092 }
5093 close(fd);
5094
5095 errnum = atol(args[1]);
5096 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5097 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005098 chunk_destroy(&curproxy->errmsg[rc]);
5099 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005100 break;
5101 }
5102 }
5103
5104 if (rc >= HTTP_ERR_SIZE) {
5105 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5106 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005108 free(err);
5109 }
5110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005112 struct cfg_kw_list *kwl;
5113 int index;
5114
5115 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5116 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5117 if (kwl->kw[index].section != CFG_LISTEN)
5118 continue;
5119 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5120 /* prepare error message just in case */
5121 snprintf(trash, sizeof(trash),
5122 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005123 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5124 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005125 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005128 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005129 else if (rc > 0) {
5130 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_WARN;
5132 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005133 }
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005135 }
5136 }
5137 }
5138
Willy Tarreau6daf3432008-01-22 16:44:08 +01005139 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005142 }
Willy Tarreau93893792009-07-23 13:19:11 +02005143 out:
5144 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145}
5146
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005147int
5148cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5149{
5150
5151 int err_code = 0;
5152 const char *err;
5153
5154 if (!strcmp(args[0], "userlist")) { /* new userlist */
5155 struct userlist *newul;
5156
5157 if (!*args[1]) {
5158 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5159 file, linenum, args[0]);
5160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
5162 }
5163
5164 err = invalid_char(args[1]);
5165 if (err) {
5166 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5167 file, linenum, *err, args[0], args[1]);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
5171
5172 for (newul = userlist; newul; newul = newul->next)
5173 if (!strcmp(newul->name, args[1])) {
5174 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5175 file, linenum, args[1]);
5176 err_code |= ERR_WARN;
5177 goto out;
5178 }
5179
5180 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5181 if (!newul) {
5182 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5183 err_code |= ERR_ALERT | ERR_ABORT;
5184 goto out;
5185 }
5186
5187 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5188 newul->name = strdup(args[1]);
5189
5190 if (!newul->groupusers | !newul->name) {
5191 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5192 err_code |= ERR_ALERT | ERR_ABORT;
5193 goto out;
5194 }
5195
5196 newul->next = userlist;
5197 userlist = newul;
5198
5199 } else if (!strcmp(args[0], "group")) { /* new group */
5200 int cur_arg, i;
5201 const char *err;
5202
5203 if (!*args[1]) {
5204 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5205 file, linenum, args[0]);
5206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209
5210 err = invalid_char(args[1]);
5211 if (err) {
5212 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5213 file, linenum, *err, args[0], args[1]);
5214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
5216 }
5217
5218 for(i = 0; i < userlist->grpcnt; i++)
5219 if (!strcmp(userlist->groups[i], args[1])) {
5220 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5221 file, linenum, args[1], userlist->name);
5222 err_code |= ERR_ALERT;
5223 goto out;
5224 }
5225
5226 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5227 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5228 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
5232
5233 cur_arg = 2;
5234
5235 while (*args[cur_arg]) {
5236 if (!strcmp(args[cur_arg], "users")) {
5237 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5238 cur_arg += 2;
5239 continue;
5240 } else {
5241 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5242 file, linenum, args[0]);
5243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246 }
5247
5248 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5249 } else if (!strcmp(args[0], "user")) { /* new user */
5250 struct auth_users *newuser;
5251 int cur_arg;
5252
5253 if (!*args[1]) {
5254 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5255 file, linenum, args[0]);
5256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
5258 }
5259
5260 for (newuser = userlist->users; newuser; newuser = newuser->next)
5261 if (!strcmp(newuser->user, args[1])) {
5262 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5263 file, linenum, args[1], userlist->name);
5264 err_code |= ERR_ALERT;
5265 goto out;
5266 }
5267
5268 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5269 if (!newuser) {
5270 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5271 err_code |= ERR_ALERT | ERR_ABORT;
5272 goto out;
5273 }
5274
5275 newuser->user = strdup(args[1]);
5276
5277 newuser->next = userlist->users;
5278 userlist->users = newuser;
5279
5280 cur_arg = 2;
5281
5282 while (*args[cur_arg]) {
5283 if (!strcmp(args[cur_arg], "password")) {
5284#ifndef CONFIG_HAP_CRYPT
5285 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5286 file, linenum);
5287 err_code |= ERR_ALERT;
5288#endif
5289 newuser->pass = strdup(args[cur_arg + 1]);
5290 cur_arg += 2;
5291 continue;
5292 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5293 newuser->pass = strdup(args[cur_arg + 1]);
5294 newuser->flags |= AU_O_INSECURE;
5295 cur_arg += 2;
5296 continue;
5297 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005298 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005299 cur_arg += 2;
5300 continue;
5301 } else {
5302 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5303 file, linenum, args[0]);
5304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
5306 }
5307 }
5308 } else {
5309 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 }
5312
5313out:
5314 return err_code;
5315}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316
5317/*
5318 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005319 * Returns the error code, 0 if OK, or any combination of :
5320 * - ERR_ABORT: must abort ASAP
5321 * - ERR_FATAL: we can continue parsing but not start the service
5322 * - ERR_WARN: a warning has been emitted
5323 * - ERR_ALERT: an alert has been emitted
5324 * Only the two first ones can stop processing, the two others are just
5325 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005327int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005329 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 FILE *f;
5331 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005333 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 if ((f=fopen(file,"r")) == NULL)
5336 return -1;
5337
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005338 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005339 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005340 char *end;
5341 char *args[MAX_LINE_ARGS + 1];
5342 char *line = thisline;
5343
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 linenum++;
5345
5346 end = line + strlen(line);
5347
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005348 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5349 /* Check if we reached the limit and the last char is not \n.
5350 * Watch out for the last line without the terminating '\n'!
5351 */
5352 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005353 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005355 }
5356
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005358 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 line++;
5360
5361 arg = 0;
5362 args[arg] = line;
5363
5364 while (*line && arg < MAX_LINE_ARGS) {
5365 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5366 * C equivalent value. Other combinations left unchanged (eg: \1).
5367 */
5368 if (*line == '\\') {
5369 int skip = 0;
5370 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5371 *line = line[1];
5372 skip = 1;
5373 }
5374 else if (line[1] == 'r') {
5375 *line = '\r';
5376 skip = 1;
5377 }
5378 else if (line[1] == 'n') {
5379 *line = '\n';
5380 skip = 1;
5381 }
5382 else if (line[1] == 't') {
5383 *line = '\t';
5384 skip = 1;
5385 }
5386 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005387 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388 unsigned char hex1, hex2;
5389 hex1 = toupper(line[2]) - '0';
5390 hex2 = toupper(line[3]) - '0';
5391 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5392 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5393 *line = (hex1<<4) + hex2;
5394 skip = 3;
5395 }
5396 else {
5397 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 }
5400 }
5401 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005402 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403 end -= skip;
5404 }
5405 line++;
5406 }
5407 else if (*line == '#' || *line == '\n' || *line == '\r') {
5408 /* end of string, end of loop */
5409 *line = 0;
5410 break;
5411 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005412 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005414 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005415 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 line++;
5417 args[++arg] = line;
5418 }
5419 else {
5420 line++;
5421 }
5422 }
5423
5424 /* empty line */
5425 if (!**args)
5426 continue;
5427
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005428 if (*line) {
5429 /* we had to stop due to too many args.
5430 * Let's terminate the string, print the offending part then cut the
5431 * last arg.
5432 */
5433 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5434 line++;
5435 *line = '\0';
5436
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005437 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005438 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005439 err_code |= ERR_ALERT | ERR_FATAL;
5440 args[arg] = line;
5441 }
5442
Willy Tarreau540abe42007-05-02 20:50:16 +02005443 /* zero out remaining args and ensure that at least one entry
5444 * is zeroed out.
5445 */
5446 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 args[arg] = line;
5448 }
5449
Willy Tarreau3842f002009-06-14 11:39:52 +02005450 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005451 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005452 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005453 for (arg=0; *args[arg+1]; arg++)
5454 args[arg] = args[arg+1]; // shift args after inversion
5455 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005456 else if (!strcmp(args[0], "default")) {
5457 kwm = KWM_DEF;
5458 for (arg=0; *args[arg+1]; arg++)
5459 args[arg] = args[arg+1]; // shift args after inversion
5460 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005461
Willy Tarreau3842f002009-06-14 11:39:52 +02005462 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5463 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005464 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005465 }
5466
Willy Tarreau977b8e42006-12-29 14:19:17 +01005467 if (!strcmp(args[0], "listen") ||
5468 !strcmp(args[0], "frontend") ||
5469 !strcmp(args[0], "backend") ||
5470 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005471 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005473 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005474 cursection = strdup(args[0]);
5475 }
5476 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005478 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005479 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005480 }
5481 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 confsect = CFG_USERLIST;
5483 free(cursection);
5484 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005485 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005486 else if (!strcmp(args[0], "peers")) {
5487 confsect = CFG_PEERS;
5488 free(cursection);
5489 cursection = strdup(args[0]);
5490 }
5491
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 /* else it's a section keyword */
5493
5494 switch (confsect) {
5495 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005496 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 break;
5498 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005499 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005501 case CFG_USERLIST:
5502 err_code |= cfg_parse_users(file, linenum, args, kwm);
5503 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005504 case CFG_PEERS:
5505 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5506 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005508 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005509 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005511
5512 if (err_code & ERR_ABORT)
5513 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005515 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005516 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005518 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005519}
5520
Willy Tarreaubb925012009-07-23 13:36:36 +02005521/*
5522 * Returns the error code, 0 if OK, or any combination of :
5523 * - ERR_ABORT: must abort ASAP
5524 * - ERR_FATAL: we can continue parsing but not start the service
5525 * - ERR_WARN: a warning has been emitted
5526 * - ERR_ALERT: an alert has been emitted
5527 * Only the two first ones can stop processing, the two others are just
5528 * indicators.
5529 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005530int check_config_validity()
5531{
5532 int cfgerr = 0;
5533 struct proxy *curproxy = NULL;
5534 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005535 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005536 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005537 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538
5539 /*
5540 * Now, check for the integrity of all that we have collected.
5541 */
5542
5543 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005544 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005546 /* first, we will invert the proxy list order */
5547 curproxy = NULL;
5548 while (proxy) {
5549 struct proxy *next;
5550
5551 next = proxy->next;
5552 proxy->next = curproxy;
5553 curproxy = proxy;
5554 if (!next)
5555 break;
5556 proxy = next;
5557 }
5558
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005560 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 }
5564
5565 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005566 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005567 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005568 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005569 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005570 unsigned int next_id;
5571
5572 if (!curproxy->uuid) {
5573 /* proxy ID not set, use automatic numbering with first
5574 * spare entry starting with next_pxid.
5575 */
5576 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5577 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5578 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005579 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005580 next_pxid++;
5581
Willy Tarreau55ea7572007-06-17 19:56:27 +02005582
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005584 /* ensure we don't keep listeners uselessly bound */
5585 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 curproxy = curproxy->next;
5587 continue;
5588 }
5589
Willy Tarreauff01a212009-03-15 13:46:16 +01005590 switch (curproxy->mode) {
5591 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005592 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005593 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5595 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005596 cfgerr++;
5597 }
5598
5599 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005600 Warning("config : servers will be ignored for %s '%s'.\n",
5601 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005602 break;
5603
5604 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005605 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005606 break;
5607
5608 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005609 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005610 break;
5611 }
5612
5613 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005614 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5615 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 cfgerr++;
5617 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005618
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005619 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005620 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005621 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005622 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005624 cfgerr++;
5625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005627 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005628 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005630 cfgerr++;
5631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005633 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005634 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5635 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005636 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005637 }
5638 }
5639 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005640 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005641 /* If no LB algo is set in a backend, and we're not in
5642 * transparent mode, dispatch mode nor proxy mode, we
5643 * want to use balance roundrobin by default.
5644 */
5645 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5646 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 }
5648 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005649
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005650 if (curproxy->options2 & PR_O2_DISPATCH) {
5651 curproxy->options &= ~PR_O_TRANSP;
5652 curproxy->options &= ~PR_O_HTTP_PROXY;
5653 }
5654 else if (curproxy->options & PR_O_HTTP_PROXY) {
5655 curproxy->options2 &= ~PR_O2_DISPATCH;
5656 curproxy->options &= ~PR_O_TRANSP;
5657 }
5658 else if (curproxy->options & PR_O_TRANSP) {
5659 curproxy->options2 &= ~PR_O2_DISPATCH;
5660 curproxy->options &= ~PR_O_HTTP_PROXY;
5661 }
5662
Willy Tarreau82936582007-11-30 15:20:09 +01005663 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5664 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005665 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5666 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005667 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005668 }
5669
Willy Tarreauef781042010-01-27 11:53:01 +01005670 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5671 curproxy->options &= ~PR_O2_CHK_SNDST;
5672 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5673 "send-state", proxy_type_str(curproxy), curproxy->id);
5674 err_code |= ERR_WARN;
5675 }
5676
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005677 /* if a default backend was specified, let's find it */
5678 if (curproxy->defbe.name) {
5679 struct proxy *target;
5680
Alex Williams96532db2009-11-01 21:27:13 -05005681 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005682 if (!target) {
5683 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5684 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005685 cfgerr++;
5686 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005687 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5688 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005689 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005690 } else {
5691 free(curproxy->defbe.name);
5692 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005693 /* we force the backend to be present on at least all of
5694 * the frontend's processes.
5695 */
5696 target->bind_proc = curproxy->bind_proc ?
5697 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
5699 }
5700
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005701 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005702 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5703 /* map jump target for ACT_SETBE in req_rep chain */
5704 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005705 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005706 struct proxy *target;
5707
Willy Tarreaua496b602006-12-17 23:15:24 +01005708 if (exp->action != ACT_SETBE)
5709 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005710
Alex Williams96532db2009-11-01 21:27:13 -05005711 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005712 if (!target) {
5713 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5714 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005715 cfgerr++;
5716 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005717 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5718 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005719 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005720 } else {
5721 free((void *)exp->replace);
5722 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005723 /* we force the backend to be present on at least all of
5724 * the frontend's processes.
5725 */
5726 target->bind_proc = curproxy->bind_proc ?
5727 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005728 }
5729 }
5730 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005731
5732 /* find the target proxy for 'use_backend' rules */
5733 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005734 struct proxy *target;
5735
Alex Williams96532db2009-11-01 21:27:13 -05005736 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005737
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005738 if (!target) {
5739 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5740 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005741 cfgerr++;
5742 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005743 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5744 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005745 cfgerr++;
5746 } else {
5747 free((void *)rule->be.name);
5748 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005749 /* we force the backend to be present on at least all of
5750 * the frontend's processes.
5751 */
5752 target->bind_proc = curproxy->bind_proc ?
5753 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005754 }
5755 }
5756
Emeric Brunb982a3d2010-01-04 15:45:53 +01005757 /* find the target table for 'stick' rules */
5758 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5759 struct proxy *target;
5760
Emeric Brun1d33b292010-01-04 15:47:17 +01005761 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5762 if (mrule->flags & STK_IS_STORE)
5763 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5764
Emeric Brunb982a3d2010-01-04 15:45:53 +01005765 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005766 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005767 else
5768 target = curproxy;
5769
5770 if (!target) {
5771 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5772 curproxy->id, mrule->table.name);
5773 cfgerr++;
5774 }
5775 else if (target->table.size == 0) {
5776 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5777 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5778 cfgerr++;
5779 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005780 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005781 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5782 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5783 cfgerr++;
5784 }
5785 else {
5786 free((void *)mrule->table.name);
5787 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005788 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 }
5790 }
5791
5792 /* find the target table for 'store response' rules */
5793 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5794 struct proxy *target;
5795
Emeric Brun1d33b292010-01-04 15:47:17 +01005796 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5797
Emeric Brunb982a3d2010-01-04 15:45:53 +01005798 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005799 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005800 else
5801 target = curproxy;
5802
5803 if (!target) {
5804 Alert("Proxy '%s': unable to find store table '%s'.\n",
5805 curproxy->id, mrule->table.name);
5806 cfgerr++;
5807 }
5808 else if (target->table.size == 0) {
5809 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5810 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5811 cfgerr++;
5812 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005813 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005814 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5815 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5816 cfgerr++;
5817 }
5818 else {
5819 free((void *)mrule->table.name);
5820 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005821 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005822 }
5823 }
5824
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005825 /* find the target table for 'tcp-request' layer 4 rules */
5826 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5827 struct proxy *target;
5828
Willy Tarreau56123282010-08-06 19:06:56 +02005829 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005830 continue;
5831
5832 if (trule->act_prm.trk_ctr.table.n)
5833 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5834 else
5835 target = curproxy;
5836
5837 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005838 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5839 curproxy->id, trule->act_prm.trk_ctr.table.n,
5840 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005841 cfgerr++;
5842 }
5843 else if (target->table.size == 0) {
5844 Alert("Proxy '%s': table '%s' used but not configured.\n",
5845 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5846 cfgerr++;
5847 }
5848 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005849 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 +02005850 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5851 cfgerr++;
5852 }
5853 else {
5854 free(trule->act_prm.trk_ctr.table.n);
5855 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005856 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005857 * to pass a list of counters to track and allocate them right here using
5858 * stktable_alloc_data_type().
5859 */
5860 }
5861 }
5862
Willy Tarreaud1f96522010-08-03 19:34:32 +02005863 /* find the target table for 'tcp-request' layer 6 rules */
5864 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5865 struct proxy *target;
5866
Willy Tarreau56123282010-08-06 19:06:56 +02005867 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005868 continue;
5869
5870 if (trule->act_prm.trk_ctr.table.n)
5871 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5872 else
5873 target = curproxy;
5874
5875 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005876 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5877 curproxy->id, trule->act_prm.trk_ctr.table.n,
5878 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005879 cfgerr++;
5880 }
5881 else if (target->table.size == 0) {
5882 Alert("Proxy '%s': table '%s' used but not configured.\n",
5883 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5884 cfgerr++;
5885 }
5886 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005887 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 +02005888 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5889 cfgerr++;
5890 }
5891 else {
5892 free(trule->act_prm.trk_ctr.table.n);
5893 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005894 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005895 * to pass a list of counters to track and allocate them right here using
5896 * stktable_alloc_data_type().
5897 */
5898 }
5899 }
5900
Emeric Brun32da3c42010-09-23 18:39:19 +02005901 if (curproxy->table.peers.name) {
5902 struct peers *curpeers = peers;
5903
5904 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5905 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5906 free((void *)curproxy->table.peers.name);
5907 curproxy->table.peers.p = peers;
5908 break;
5909 }
5910 }
5911
5912 if (!curpeers) {
5913 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5914 curproxy->id, curproxy->table.peers.name);
5915 cfgerr++;
5916 }
5917 else if (!curpeers->peers_fe) {
5918 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5919 curproxy->id, curpeers->id);
5920 cfgerr++;
5921 }
5922 }
5923
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005924 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005925 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5927 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5928 "proxy", curproxy->id);
5929 cfgerr++;
5930 goto out_uri_auth_compat;
5931 }
5932
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005933 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005934 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005935 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005936 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005937
Willy Tarreau95fa4692010-02-01 13:05:50 +01005938 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5939 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005940
5941 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005942 uri_auth_compat_req[i++] = "realm";
5943 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5944 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005945
Willy Tarreau95fa4692010-02-01 13:05:50 +01005946 uri_auth_compat_req[i++] = "unless";
5947 uri_auth_compat_req[i++] = "{";
5948 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5949 uri_auth_compat_req[i++] = "}";
5950 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005951
Willy Tarreauff011f22011-01-06 17:51:27 +01005952 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5953 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005954 cfgerr++;
5955 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005956 }
5957
Willy Tarreauff011f22011-01-06 17:51:27 +01005958 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005959
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005960 if (curproxy->uri_auth->auth_realm) {
5961 free(curproxy->uri_auth->auth_realm);
5962 curproxy->uri_auth->auth_realm = NULL;
5963 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005964
5965 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005966 }
5967out_uri_auth_compat:
5968
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005969 cfgerr += acl_find_targets(curproxy);
5970
Willy Tarreau2738a142006-07-08 17:28:09 +02005971 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005972 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005973 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005974 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005975 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005976 " | While not properly invalid, you will certainly encounter various problems\n"
5977 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005978 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005979 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005980 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005981 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005982
Willy Tarreau1fa31262007-12-03 00:36:16 +01005983 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5984 * We must still support older configurations, so let's find out whether those
5985 * parameters have been set or must be copied from contimeouts.
5986 */
5987 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005988 if (!curproxy->timeout.tarpit ||
5989 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005990 /* tarpit timeout not set. We search in the following order:
5991 * default.tarpit, curr.connect, default.connect.
5992 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005993 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005994 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005995 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005996 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005997 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005998 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005999 }
6000 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006001 (!curproxy->timeout.queue ||
6002 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006003 /* queue timeout not set. We search in the following order:
6004 * default.queue, curr.connect, default.connect.
6005 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006006 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006007 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006008 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006009 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006010 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006011 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006012 }
6013 }
6014
Willy Tarreau07a54902010-03-29 18:33:29 +02006015 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006016 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6017 curproxy->check_req = (char *)malloc(curproxy->check_len);
6018 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006019 }
6020
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006021 /* The small pools required for the capture lists */
6022 if (curproxy->nb_req_cap)
6023 curproxy->req_cap_pool = create_pool("ptrcap",
6024 curproxy->nb_req_cap * sizeof(char *),
6025 MEM_F_SHARED);
6026 if (curproxy->nb_rsp_cap)
6027 curproxy->rsp_cap_pool = create_pool("ptrcap",
6028 curproxy->nb_rsp_cap * sizeof(char *),
6029 MEM_F_SHARED);
6030
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006031 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6032 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6033 MEM_F_SHARED);
6034
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 /* first, we will invert the servers list order */
6036 newsrv = NULL;
6037 while (curproxy->srv) {
6038 struct server *next;
6039
6040 next = curproxy->srv->next;
6041 curproxy->srv->next = newsrv;
6042 newsrv = curproxy->srv;
6043 if (!next)
6044 break;
6045 curproxy->srv = next;
6046 }
6047
Willy Tarreaudd701652010-05-25 23:03:02 +02006048 /* assign automatic UIDs to servers which don't have one yet */
6049 next_id = 1;
6050 newsrv = curproxy->srv;
6051 while (newsrv != NULL) {
6052 if (!newsrv->puid) {
6053 /* server ID not set, use automatic numbering with first
6054 * spare entry starting with next_svid.
6055 */
6056 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6057 newsrv->conf.id.key = newsrv->puid = next_id;
6058 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6059 }
6060 next_id++;
6061 newsrv = newsrv->next;
6062 }
6063
Willy Tarreau20697042007-11-15 23:26:18 +01006064 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006065 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006066
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006067 /* We have to initialize the server lookup mechanism depending
6068 * on what LB algorithm was choosen.
6069 */
6070
6071 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6072 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6073 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006074 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6075 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6076 init_server_map(curproxy);
6077 } else {
6078 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6079 fwrr_init_server_groups(curproxy);
6080 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006081 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006082
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006083 case BE_LB_KIND_LC:
6084 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006085 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006086 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006087
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006088 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006089 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6090 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6091 chash_init_server_tree(curproxy);
6092 } else {
6093 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6094 init_server_map(curproxy);
6095 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006096 break;
6097 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006098
6099 if (curproxy->options & PR_O_LOGASAP)
6100 curproxy->to_log &= ~LW_BYTES;
6101
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006102 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6103 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6104 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6105 proxy_type_str(curproxy), curproxy->id);
6106 err_code |= ERR_WARN;
6107 }
6108
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006109 if (curproxy->mode != PR_MODE_HTTP) {
6110 int optnum;
6111
6112 if (curproxy->options & PR_O_COOK_ANY) {
6113 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6114 proxy_type_str(curproxy), curproxy->id);
6115 err_code |= ERR_WARN;
6116 }
6117
6118 if (curproxy->uri_auth) {
6119 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6120 proxy_type_str(curproxy), curproxy->id);
6121 err_code |= ERR_WARN;
6122 curproxy->uri_auth = NULL;
6123 }
6124
6125 if (curproxy->options & PR_O_FWDFOR) {
6126 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6127 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6128 err_code |= ERR_WARN;
6129 curproxy->options &= ~PR_O_FWDFOR;
6130 }
6131
6132 if (curproxy->options & PR_O_ORGTO) {
6133 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6134 "originalto", proxy_type_str(curproxy), curproxy->id);
6135 err_code |= ERR_WARN;
6136 curproxy->options &= ~PR_O_ORGTO;
6137 }
6138
6139 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6140 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6141 (curproxy->cap & cfg_opts[optnum].cap) &&
6142 (curproxy->options & cfg_opts[optnum].val)) {
6143 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6144 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6145 err_code |= ERR_WARN;
6146 curproxy->options &= ~cfg_opts[optnum].val;
6147 }
6148 }
6149
6150 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6151 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6152 (curproxy->cap & cfg_opts2[optnum].cap) &&
6153 (curproxy->options2 & cfg_opts2[optnum].val)) {
6154 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6155 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6156 err_code |= ERR_WARN;
6157 curproxy->options2 &= ~cfg_opts2[optnum].val;
6158 }
6159 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006160
Willy Tarreauefa5f512010-03-30 20:13:29 +02006161#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006162 if (curproxy->bind_hdr_occ) {
6163 curproxy->bind_hdr_occ = 0;
6164 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6165 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6166 err_code |= ERR_WARN;
6167 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006168#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006169 }
6170
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006172 * ensure that we're not cross-dressing a TCP server into HTTP.
6173 */
6174 newsrv = curproxy->srv;
6175 while (newsrv != NULL) {
6176 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006177 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6178 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006179 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006180 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006181
Willy Tarreauefa5f512010-03-30 20:13:29 +02006182#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006183 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6184 newsrv->bind_hdr_occ = 0;
6185 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6186 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6187 err_code |= ERR_WARN;
6188 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006189#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006190 newsrv = newsrv->next;
6191 }
6192
6193 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 * If this server supports a maxconn parameter, it needs a dedicated
6195 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006196 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 */
6198 newsrv = curproxy->srv;
6199 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006200 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 /* Only 'minconn' was specified, or it was higher than or equal
6202 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6203 * this will avoid further useless expensive computations.
6204 */
6205 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006206 } else if (newsrv->maxconn && !newsrv->minconn) {
6207 /* minconn was not specified, so we set it to maxconn */
6208 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 }
6210
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006211 if (newsrv->trackit) {
6212 struct proxy *px;
6213 struct server *srv;
6214 char *pname, *sname;
6215
6216 pname = newsrv->trackit;
6217 sname = strrchr(pname, '/');
6218
6219 if (sname)
6220 *sname++ = '\0';
6221 else {
6222 sname = pname;
6223 pname = NULL;
6224 }
6225
6226 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006227 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006229 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6230 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 cfgerr++;
6233 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 }
6235 } else
6236 px = curproxy;
6237
6238 srv = findserver(px, sname);
6239 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006240 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6241 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006242 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006243 cfgerr++;
6244 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006245 }
6246
6247 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006248 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006249 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006250 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006251 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006252 cfgerr++;
6253 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006254 }
6255
6256 if (curproxy != px &&
6257 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006258 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006259 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006260 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006261 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006262 cfgerr++;
6263 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006264 }
6265
6266 newsrv->tracked = srv;
6267 newsrv->tracknext = srv->tracknext;
6268 srv->tracknext = newsrv;
6269
6270 free(newsrv->trackit);
6271 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006272 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006273 newsrv = newsrv->next;
6274 }
6275
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006277 curproxy->accept = frontend_accept;
6278
Willy Tarreauc1a21672009-08-16 22:37:44 +02006279 if (curproxy->tcp_req.inspect_delay ||
6280 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006281 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006282
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006283 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006284 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006285 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006286 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006287
6288 /* both TCP and HTTP must check switching rules */
6289 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6290 }
6291
6292 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006293 if (curproxy->tcp_req.inspect_delay ||
6294 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6295 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6296
Emeric Brun97679e72010-09-23 17:56:44 +02006297 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6298 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6299
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006300 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006301 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006302 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006303 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006304
6305 /* If the backend does requires RDP cookie persistence, we have to
6306 * enable the corresponding analyser.
6307 */
6308 if (curproxy->options2 & PR_O2_RDPC_PRST)
6309 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6310 }
6311
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006312 listener = NULL;
6313 while (curproxy->listen) {
6314 struct listener *next;
6315
6316 next = curproxy->listen->next;
6317 curproxy->listen->next = listener;
6318 listener = curproxy->listen;
6319
6320 if (!next)
6321 break;
6322
6323 curproxy->listen = next;
6324 }
6325
Willy Tarreaue6b98942007-10-29 01:09:36 +01006326 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006327 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006328 listener = curproxy->listen;
6329 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006330 if (!listener->luid) {
6331 /* listener ID not set, use automatic numbering with first
6332 * spare entry starting with next_luid.
6333 */
6334 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6335 listener->conf.id.key = listener->luid = next_id;
6336 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006337 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006338 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006339
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006340 /* enable separate counters */
6341 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6342 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6343 if (!listener->name) {
6344 sprintf(trash, "sock-%d", listener->luid);
6345 listener->name = strdup(trash);
6346 }
6347 }
6348
Willy Tarreaue6b98942007-10-29 01:09:36 +01006349 if (curproxy->options & PR_O_TCP_NOLING)
6350 listener->options |= LI_O_NOLINGER;
6351 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006352 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006353 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006354 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006355 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006356 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006357 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006358
Willy Tarreau8a956912010-10-15 14:27:08 +02006359 if (listener->options & LI_O_ACC_PROXY)
6360 listener->analysers |= AN_REQ_DECODE_PROXY;
6361
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006362 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6363 listener->options |= LI_O_TCP_RULES;
6364
Willy Tarreaude3041d2010-05-31 10:56:17 +02006365 if (curproxy->mon_mask.s_addr)
6366 listener->options |= LI_O_CHK_MONNET;
6367
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006368 /* smart accept mode is automatic in HTTP mode */
6369 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6370 (curproxy->mode == PR_MODE_HTTP &&
6371 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6372 listener->options |= LI_O_NOQUICKACK;
6373
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006374 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006375 listener = listener->next;
6376 }
6377
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006378 /* Check multi-process mode compatibility for the current proxy */
6379 if (global.nbproc > 1) {
6380 int nbproc = 0;
6381 if (curproxy->bind_proc) {
6382 int proc;
6383 for (proc = 0; proc < global.nbproc; proc++) {
6384 if (curproxy->bind_proc & (1 << proc)) {
6385 nbproc++;
6386 }
6387 }
6388 } else {
6389 nbproc = global.nbproc;
6390 }
6391 if (curproxy->table.peers.name) {
6392 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6393 curproxy->id);
6394 cfgerr++;
6395 }
6396 if (nbproc > 1) {
6397 if (curproxy->uri_auth) {
6398 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6399 curproxy->id);
6400 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6401 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6402 curproxy->id);
6403 }
6404 }
6405 if (curproxy->appsession_name) {
6406 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6407 curproxy->id);
6408 }
6409 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6410 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6411 curproxy->id);
6412 }
6413 }
6414 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006415
6416 /* create the task associated with the proxy */
6417 curproxy->task = task_new();
6418 if (curproxy->task) {
6419 curproxy->task->context = curproxy;
6420 curproxy->task->process = manage_proxy;
6421 /* no need to queue, it will be done automatically if some
6422 * listener gets limited.
6423 */
6424 curproxy->task->expire = TICK_ETERNITY;
6425 } else {
6426 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6427 curproxy->id);
6428 cfgerr++;
6429 }
6430
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 curproxy = curproxy->next;
6432 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006433
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006434 /* Check multi-process mode compatibility */
6435 if (global.nbproc > 1) {
6436 if (global.stats_fe) {
6437 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6438 }
6439 }
6440
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006441 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6442 struct auth_users *curuser;
6443 int g;
6444
6445 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6446 unsigned int group_mask = 0;
6447 char *group = NULL;
6448
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006449 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006450 continue;
6451
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006452 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006453
6454 for (g = 0; g < curuserlist->grpcnt; g++)
6455 if (!strcmp(curuserlist->groups[g], group))
6456 break;
6457
6458 if (g == curuserlist->grpcnt) {
6459 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6460 curuserlist->name, group, curuser->user);
6461 err_code |= ERR_ALERT | ERR_FATAL;
6462 goto out;
6463 }
6464
6465 group_mask |= (1 << g);
6466 }
6467
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006468 free(curuser->u.groups);
6469 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006470 }
6471
6472 for (g = 0; g < curuserlist->grpcnt; g++) {
6473 char *user = NULL;
6474
6475 if (!curuserlist->groupusers[g])
6476 continue;
6477
6478 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6479 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6480 if (!strcmp(curuser->user, user))
6481 break;
6482
6483 if (!curuser) {
6484 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6485 curuserlist->name, user, curuserlist->groups[g]);
6486 err_code |= ERR_ALERT | ERR_FATAL;
6487 goto out;
6488 }
6489
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006490 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006491 }
6492
6493 free(curuserlist->groupusers[g]);
6494 }
6495
6496 free(curuserlist->groupusers);
6497
6498#ifdef DEBUG_AUTH
6499 for (g = 0; g < curuserlist->grpcnt; g++) {
6500 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6501
6502 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6503 if (curuser->group_mask & (1 << g))
6504 fprintf(stderr, " %s", curuser->user);
6505 }
6506
6507 fprintf(stderr, "\n");
6508 }
6509#endif
6510
Willy Tarreaufbb78422011-06-05 15:38:35 +02006511 }
6512
6513 /* automatically compute fullconn if not set. We must not do it in the
6514 * loop above because cross-references are not yet fully resolved.
6515 */
6516 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6517 /* If <fullconn> is not set, let's set it to 10% of the sum of
6518 * the possible incoming frontend's maxconns.
6519 */
6520 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6521 struct proxy *fe;
6522 int total = 0;
6523
6524 /* sum up the number of maxconns of frontends which
6525 * reference this backend at least once or which are
6526 * the same one ('listen').
6527 */
6528 for (fe = proxy; fe; fe = fe->next) {
6529 struct switching_rule *rule;
6530 struct hdr_exp *exp;
6531 int found = 0;
6532
6533 if (!(fe->cap & PR_CAP_FE))
6534 continue;
6535
6536 if (fe == curproxy) /* we're on a "listen" instance */
6537 found = 1;
6538
6539 if (fe->defbe.be == curproxy) /* "default_backend" */
6540 found = 1;
6541
6542 /* check if a "use_backend" rule matches */
6543 if (!found) {
6544 list_for_each_entry(rule, &fe->switching_rules, list) {
6545 if (rule->be.backend == curproxy) {
6546 found = 1;
6547 break;
6548 }
6549 }
6550 }
6551
6552 /* check if a "reqsetbe" rule matches */
6553 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6554 if (exp->action == ACT_SETBE &&
6555 (struct proxy *)exp->replace == curproxy) {
6556 found = 1;
6557 break;
6558 }
6559 }
6560
6561 /* now we've checked all possible ways to reference a backend
6562 * from a frontend.
6563 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006564 if (!found)
6565 continue;
6566 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006567 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006568 /* we have the sum of the maxconns in <total>. We only
6569 * keep 10% of that sum to set the default fullconn, with
6570 * a hard minimum of 1 (to avoid a divide by zero).
6571 */
6572 curproxy->fullconn = (total + 9) / 10;
6573 if (!curproxy->fullconn)
6574 curproxy->fullconn = 1;
6575 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006576 }
6577
Willy Tarreau056f5682010-06-06 15:51:11 +02006578 /* initialize stick-tables on backend capable proxies. This must not
6579 * be done earlier because the data size may be discovered while parsing
6580 * other proxies.
6581 */
6582 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006583 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006584
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006585 /*
6586 * Recount currently required checks.
6587 */
6588
6589 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6590 int optnum;
6591
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006592 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6593 if (curproxy->options & cfg_opts[optnum].val)
6594 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006595
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006596 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6597 if (curproxy->options2 & cfg_opts2[optnum].val)
6598 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006599 }
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 */