blob: 7b46df0bf26e186d4ce926607973cf7fca380c4b [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 Tarreau97cb7802010-01-03 20:23:58 +01001044
1045 /* Timeouts are defined as -1 */
1046 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001047 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001048}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001050void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001052 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 defproxy.mode = PR_MODE_TCP;
1054 defproxy.state = PR_STNEW;
1055 defproxy.maxconn = cfg_maxpconn;
1056 defproxy.conn_retries = CONN_RETRIES;
1057 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001058
1059 defproxy.defsrv.inter = DEF_CHKINTR;
1060 defproxy.defsrv.fastinter = 0;
1061 defproxy.defsrv.downinter = 0;
1062 defproxy.defsrv.rise = DEF_RISETIME;
1063 defproxy.defsrv.fall = DEF_FALLTIME;
1064 defproxy.defsrv.check_port = 0;
1065 defproxy.defsrv.maxqueue = 0;
1066 defproxy.defsrv.minconn = 0;
1067 defproxy.defsrv.maxconn = 0;
1068 defproxy.defsrv.slowstart = 0;
1069 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1070 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1071 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072}
1073
Willy Tarreauade5ec42010-01-28 19:33:49 +01001074
1075static int create_cond_regex_rule(const char *file, int line,
1076 struct proxy *px, int dir, int action, int flags,
1077 const char *cmd, const char *reg, const char *repl,
1078 const char **cond_start)
1079{
1080 regex_t *preg = NULL;
1081 const char *err;
1082 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001083 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001084
1085 if (px == &defproxy) {
1086 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto err;
1089 }
1090
1091 if (*reg == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1098 err_code |= ERR_WARN;
1099
Willy Tarreau5321c422010-01-28 20:35:13 +01001100 if (cond_start &&
1101 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1102 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1103 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1104 file, line, cmd);
1105 err_code |= ERR_ALERT | ERR_FATAL;
1106 goto err;
1107 }
1108 }
1109 else if (cond_start && **cond_start) {
1110 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1111 file, line, cmd, *cond_start);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ)
1117 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001118 else
1119 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001120
Willy Tarreauade5ec42010-01-28 19:33:49 +01001121 preg = calloc(1, sizeof(regex_t));
1122 if (!preg) {
1123 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1124 err_code = ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127
1128 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1129 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001135 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001136 if (repl && err) {
1137 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1138 file, line, cmd, *err);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1144 err_code |= ERR_WARN;
1145
1146 return err_code;
1147 err:
1148 free(preg);
1149 return err_code;
1150}
1151
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001153 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001154 * Returns the error code, 0 if OK, or any combination of :
1155 * - ERR_ABORT: must abort ASAP
1156 * - ERR_FATAL: we can continue parsing but not start the service
1157 * - ERR_WARN: a warning has been emitted
1158 * - ERR_ALERT: an alert has been emitted
1159 * Only the two first ones can stop processing, the two others are just
1160 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001161 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001162int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1163{
1164 static struct peers *curpeers = NULL;
1165 struct peer *newpeer = NULL;
1166 const char *err;
1167 int err_code = 0;
1168
1169 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1170
1171 err = invalid_char(args[1]);
1172 if (err) {
1173 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1174 file, linenum, *err, args[0], args[1]);
1175 err_code |= ERR_ALERT | ERR_FATAL;
1176 }
1177
1178 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1179 /*
1180 * If there are two proxies with the same name only following
1181 * combinations are allowed:
1182 */
1183 if (strcmp(curpeers->id, args[1]) == 0) {
1184 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1185 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1186 err_code |= ERR_WARN;
1187 }
1188 }
1189
1190 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1191 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1192 err_code |= ERR_ALERT | ERR_ABORT;
1193 goto out;
1194 }
1195
1196 curpeers->next = peers;
1197 peers = curpeers;
1198 curpeers->conf.file = file;
1199 curpeers->conf.line = linenum;
1200 curpeers->last_change = now.tv_sec;
1201 curpeers->id = strdup(args[1]);
1202 }
1203 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1204 char *rport, *raddr;
1205 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001206 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001207
1208 if (!*args[2]) {
1209 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1210 file, linenum, args[0]);
1211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
1213 }
1214
1215 err = invalid_char(args[1]);
1216 if (err) {
1217 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1218 file, linenum, *err, args[1]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222
1223 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1225 err_code |= ERR_ALERT | ERR_ABORT;
1226 goto out;
1227 }
1228
1229 /* the peers are linked backwards first */
1230 curpeers->count++;
1231 newpeer->next = curpeers->remote;
1232 curpeers->remote = newpeer;
1233 newpeer->peers = curpeers;
1234 newpeer->conf.file = file;
1235 newpeer->conf.line = linenum;
1236
1237 newpeer->last_change = now.tv_sec;
1238 newpeer->id = strdup(args[1]);
1239
1240 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001241 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001242 if (rport) {
1243 *rport++ = 0;
1244 realport = atol(rport);
1245 }
1246 if (!realport) {
1247 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251
Willy Tarreaufab5a432011-03-04 15:31:53 +01001252 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001253 free(raddr);
1254 if (!sk) {
1255 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001260
1261 switch (newpeer->addr.ss_family) {
1262 case AF_INET:
1263 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1264 break;
1265 case AF_INET6:
1266 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1267 break;
1268 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001269
1270 if (strcmp(newpeer->id, localpeer) == 0) {
1271 /* Current is local peer, it define a frontend */
1272 newpeer->local = 1;
1273
1274 if (!curpeers->peers_fe) {
1275 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1276 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1277 err_code |= ERR_ALERT | ERR_ABORT;
1278 goto out;
1279 }
1280 curpeers->peers_fe->parent = curpeers;
1281
1282 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1283 LIST_INIT(&(curpeers->peers_fe)->acl);
1284 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1285 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1286 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1287 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1288 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1289 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1290
1291 proxy_reset_timeouts(curpeers->peers_fe);
1292
1293 curpeers->peers_fe->last_change = now.tv_sec;
1294 curpeers->peers_fe->id = strdup(args[1]);
1295 curpeers->peers_fe->cap = PR_CAP_FE;
1296 curpeers->peers_fe->maxconn = 65000;
1297 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1298 curpeers->peers_fe->timeout.connect = 5000;
1299 curpeers->peers_fe->accept = peer_accept;
1300 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001301 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001302 err_code |= ERR_FATAL;
1303 goto out;
1304 }
1305 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1306 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1307 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1308 curpeers->peers_fe->listen->accept = session_accept;
1309 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1310 curpeers->peers_fe->listen->handler = process_session;
1311 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1312 }
1313 }
1314 } /* neither "peer" nor "peers" */
1315 else if (*args[0] != 0) {
1316 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
1320
1321out:
1322 return err_code;
1323}
1324
1325
Willy Tarreau3842f002009-06-14 11:39:52 +02001326int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327{
1328 static struct proxy *curproxy = NULL;
1329 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001330 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001331 int rc;
1332 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001333 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001334 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335
Willy Tarreau977b8e42006-12-29 14:19:17 +01001336 if (!strcmp(args[0], "listen"))
1337 rc = PR_CAP_LISTEN;
1338 else if (!strcmp(args[0], "frontend"))
1339 rc = PR_CAP_FE | PR_CAP_RS;
1340 else if (!strcmp(args[0], "backend"))
1341 rc = PR_CAP_BE | PR_CAP_RS;
1342 else if (!strcmp(args[0], "ruleset"))
1343 rc = PR_CAP_RS;
1344 else
1345 rc = PR_CAP_NONE;
1346
1347 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 if (!*args[1]) {
1349 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1350 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1351 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_ABORT;
1353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001355
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001356 err = invalid_char(args[1]);
1357 if (err) {
1358 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1359 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001361 }
1362
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001363 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1364 /*
1365 * If there are two proxies with the same name only following
1366 * combinations are allowed:
1367 *
1368 * listen backend frontend ruleset
1369 * listen - - - -
1370 * backend - - OK -
1371 * frontend - OK - -
1372 * ruleset - - - -
1373 */
1374
1375 if (!strcmp(curproxy->id, args[1]) &&
1376 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1377 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001378 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1379 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1380 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001382 }
1383 }
1384
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1386 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001387 err_code |= ERR_ALERT | ERR_ABORT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001390
Willy Tarreau97cb7802010-01-03 20:23:58 +01001391 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392 curproxy->next = proxy;
1393 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 curproxy->conf.file = file;
1395 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001396 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001397 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001398 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399
1400 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001401 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001402 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001403 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001404 err_code |= ERR_FATAL;
1405 goto out;
1406 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 new = curproxy->listen;
1408 while (new != last) {
1409 new->conf.file = file;
1410 new->conf.line = linenum;
1411 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001412 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001413 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 }
1415
1416 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001417 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001418 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001422 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001423 curproxy->no_options = defproxy.no_options;
1424 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001425 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001426 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001427 curproxy->except_net = defproxy.except_net;
1428 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001429 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001430 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001432 if (defproxy.fwdfor_hdr_len) {
1433 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1434 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1435 }
1436
Willy Tarreaub86db342009-11-30 11:50:16 +01001437 if (defproxy.orgto_hdr_len) {
1438 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1439 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1440 }
1441
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442 if (curproxy->cap & PR_CAP_FE) {
1443 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001444 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001445 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446
1447 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001448 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1449 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001450
1451 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1452 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453
Willy Tarreau977b8e42006-12-29 14:19:17 +01001454 if (curproxy->cap & PR_CAP_BE) {
1455 curproxy->fullconn = defproxy.fullconn;
1456 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001458 if (defproxy.check_req) {
1459 curproxy->check_req = calloc(1, defproxy.check_len);
1460 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1461 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001462 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 if (defproxy.cookie_name)
1465 curproxy->cookie_name = strdup(defproxy.cookie_name);
1466 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001467 if (defproxy.cookie_domain)
1468 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001469
Willy Tarreau31936852010-10-06 16:59:56 +02001470 if (defproxy.cookie_maxidle)
1471 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1472
1473 if (defproxy.cookie_maxlife)
1474 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1475
Emeric Brun647caf12009-06-30 17:57:00 +02001476 if (defproxy.rdp_cookie_name)
1477 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1478 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1479
Willy Tarreau01732802007-11-01 22:48:15 +01001480 if (defproxy.url_param_name)
1481 curproxy->url_param_name = strdup(defproxy.url_param_name);
1482 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001483
Benoitaffb4812009-03-25 13:02:10 +01001484 if (defproxy.hh_name)
1485 curproxy->hh_name = strdup(defproxy.hh_name);
1486 curproxy->hh_len = defproxy.hh_len;
1487 curproxy->hh_match_domain = defproxy.hh_match_domain;
1488
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001489 if (defproxy.iface_name)
1490 curproxy->iface_name = strdup(defproxy.iface_name);
1491 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001494 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if (defproxy.capture_name)
1496 curproxy->capture_name = strdup(defproxy.capture_name);
1497 curproxy->capture_namelen = defproxy.capture_namelen;
1498 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001502 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001503 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001504 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001505 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001506 curproxy->uri_auth = defproxy.uri_auth;
1507 curproxy->mon_net = defproxy.mon_net;
1508 curproxy->mon_mask = defproxy.mon_mask;
1509 if (defproxy.monitor_uri)
1510 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1511 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001512 if (defproxy.defbe.name)
1513 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 }
1515
1516 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001517 curproxy->timeout.connect = defproxy.timeout.connect;
1518 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001519 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001520 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001521 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001522 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001523 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 curproxy->source_addr = defproxy.source_addr;
1525 }
1526
Willy Tarreaubaaee002006-06-26 02:48:02 +02001527 curproxy->mode = defproxy.mode;
1528 curproxy->logfac1 = defproxy.logfac1;
1529 curproxy->logsrv1 = defproxy.logsrv1;
1530 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001531 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 curproxy->logfac2 = defproxy.logfac2;
1533 curproxy->logsrv2 = defproxy.logsrv2;
1534 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001535 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001537 curproxy->conf.used_listener_id = EB_ROOT;
1538 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001539
Willy Tarreau93893792009-07-23 13:19:11 +02001540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541 }
1542 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1543 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001544 /* FIXME-20070101: we should do this too at the end of the
1545 * config parsing to free all default values.
1546 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001547 free(defproxy.check_req);
1548 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001549 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001550 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001551 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001552 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 free(defproxy.capture_name);
1554 free(defproxy.monitor_uri);
1555 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001556 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001557 free(defproxy.fwdfor_hdr_name);
1558 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001559 free(defproxy.orgto_hdr_name);
1560 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001561
Willy Tarreaua534fea2008-08-03 12:19:50 +02001562 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001563 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 /* we cannot free uri_auth because it might already be used */
1566 init_default_instance();
1567 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 else if (curproxy == NULL) {
1572 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 }
1576
Willy Tarreau977b8e42006-12-29 14:19:17 +01001577
1578 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001580 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001581 int cur_arg;
1582
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (curproxy == &defproxy) {
1584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001589 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590
Emeric Bruned760922010-10-22 17:59:25 +02001591 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001592 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001597
1598 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001599
1600 /* NOTE: the following line might create several listeners if there
1601 * are comma-separated IPs or port ranges. So all further processing
1602 * will have to be applied to all listeners created after last_listen.
1603 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001604 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
1607 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001608
Willy Tarreau90a570f2009-10-04 20:54:54 +02001609 new_listen = curproxy->listen;
1610 while (new_listen != last_listen) {
1611 new_listen->conf.file = file;
1612 new_listen->conf.line = linenum;
1613 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001614 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001615 }
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 /* Set default global rights and owner for unix bind */
1618 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1619 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1620 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001621 cur_arg = 2;
1622 while (*(args[cur_arg])) {
1623 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1624#ifdef SO_BINDTODEVICE
1625 struct listener *l;
1626
Emeric Bruned760922010-10-22 17:59:25 +02001627 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1628 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1629 file, linenum, args[0], args[cur_arg]);
1630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
1632 }
1633
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001634 if (!*args[cur_arg + 1]) {
1635 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001639 }
1640
1641 for (l = curproxy->listen; l != last_listen; l = l->next)
1642 l->interface = strdup(args[cur_arg + 1]);
1643
1644 global.last_checks |= LSTCHK_NETADM;
1645
1646 cur_arg += 2;
1647 continue;
1648#else
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1650 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001653#endif
1654 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001655 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1656#ifdef TCP_MAXSEG
1657 struct listener *l;
1658 int mss;
1659
Emeric Bruned760922010-10-22 17:59:25 +02001660 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1661 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1662 file, linenum, args[0], args[cur_arg]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
1666
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001672 }
1673
Willy Tarreau48a7e722010-12-24 15:26:39 +01001674 mss = atoi(args[cur_arg + 1]);
1675 if (!mss || abs(mss) > 65535) {
1676 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001677 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001678 err_code |= ERR_ALERT | ERR_FATAL;
1679 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001680 }
1681
1682 for (l = curproxy->listen; l != last_listen; l = l->next)
1683 l->maxseg = mss;
1684
1685 cur_arg += 2;
1686 continue;
1687#else
1688 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1689 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001692#endif
1693 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001694
1695 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1696#ifdef TCP_DEFER_ACCEPT
1697 struct listener *l;
1698
1699 for (l = curproxy->listen; l != last_listen; l = l->next)
1700 l->options |= LI_O_DEF_ACCEPT;
1701
1702 cur_arg ++;
1703 continue;
1704#else
1705 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1706 file, linenum, args[0], args[cur_arg]);
1707 err_code |= ERR_ALERT | ERR_FATAL;
1708 goto out;
1709#endif
1710 }
1711
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001712 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001714 struct listener *l;
1715
Emeric Bruned760922010-10-22 17:59:25 +02001716 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1717 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1718 file, linenum, args[0], args[cur_arg]);
1719 err_code |= ERR_ALERT | ERR_FATAL;
1720 goto out;
1721 }
1722
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001723 for (l = curproxy->listen; l != last_listen; l = l->next)
1724 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001725
1726 cur_arg ++;
1727 continue;
1728#else
1729 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1730 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_FATAL;
1732 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001735
Willy Tarreau8a956912010-10-15 14:27:08 +02001736 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->options |= LI_O_ACC_PROXY;
1741
1742 cur_arg ++;
1743 continue;
1744 }
1745
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001746 if (!strcmp(args[cur_arg], "name")) {
1747 struct listener *l;
1748
1749 for (l = curproxy->listen; l != last_listen; l = l->next)
1750 l->name = strdup(args[cur_arg + 1]);
1751
1752 cur_arg += 2;
1753 continue;
1754 }
1755
1756 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001757 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001758 struct listener *l;
1759
1760 if (curproxy->listen->next != last_listen) {
1761 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1762 file, linenum, args[cur_arg]);
1763 err_code |= ERR_ALERT | ERR_FATAL;
1764 goto out;
1765 }
1766
1767 if (!*args[cur_arg + 1]) {
1768 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1769 file, linenum, args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001775 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001776
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001777 if (curproxy->listen->luid <= 0) {
1778 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 file, linenum);
1780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001784 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1785 if (node) {
1786 l = container_of(node, struct listener, conf.id);
1787 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1788 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1789 err_code |= ERR_ALERT | ERR_FATAL;
1790 goto out;
1791 }
1792 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1793
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001794 cur_arg += 2;
1795 continue;
1796 }
1797
Emeric Bruned760922010-10-22 17:59:25 +02001798 if (!strcmp(args[cur_arg], "mode")) {
1799
1800 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1801 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1802 file, linenum, args[0], args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
1807 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1808
1809 cur_arg += 2;
1810 continue;
1811 }
1812
1813 if (!strcmp(args[cur_arg], "uid")) {
1814
1815 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1816 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1817 file, linenum, args[0], args[cur_arg]);
1818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
1822 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1823 cur_arg += 2;
1824 continue;
1825 }
1826
1827 if (!strcmp(args[cur_arg], "gid")) {
1828
1829 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1830 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1831 file, linenum, args[0], args[cur_arg]);
1832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
1836 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1837 cur_arg += 2;
1838 continue;
1839 }
1840
1841 if (!strcmp(args[cur_arg], "user")) {
1842 struct passwd *user;
1843
1844 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1845 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1846 file, linenum, args[0], args[cur_arg]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850 user = getpwnam(args[cur_arg + 1]);
1851 if (!user) {
1852 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1853 file, linenum, args[0], args[cur_arg + 1 ]);
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857
1858 curproxy->listen->perm.ux.uid = user->pw_uid;
1859 cur_arg += 2;
1860 continue;
1861 }
1862
1863 if (!strcmp(args[cur_arg], "group")) {
1864 struct group *group;
1865
1866 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1867 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1868 file, linenum, args[0], args[cur_arg]);
1869 err_code |= ERR_ALERT | ERR_FATAL;
1870 goto out;
1871 }
1872 group = getgrnam(args[cur_arg + 1]);
1873 if (!group) {
1874 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1875 file, linenum, args[0], args[cur_arg + 1 ]);
1876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
1878 }
1879
1880 curproxy->listen->perm.ux.gid = group->gr_gid;
1881 cur_arg += 2;
1882 continue;
1883 }
1884
Willy Tarreau8a956912010-10-15 14:27:08 +02001885 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 +01001886 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001889 }
Willy Tarreau93893792009-07-23 13:19:11 +02001890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891 }
1892 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1893 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1894 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 /* flush useless bits */
1903 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001906 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 if (!*args[1]) {
1911 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001915 }
1916
Willy Tarreaua534fea2008-08-03 12:19:50 +02001917 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001918 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001920 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001921 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1922
Willy Tarreau93893792009-07-23 13:19:11 +02001923 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1926 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1927 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1928 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1929 else {
1930 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933 }
1934 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001936 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001937
1938 if (curproxy == &defproxy) {
1939 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001943 }
1944
1945 if (!*args[1]) {
1946 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1947 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950 }
1951
1952 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001955 if (curproxy->uuid <= 0) {
1956 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001960 }
1961
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001962 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1963 if (node) {
1964 struct proxy *target = container_of(node, struct proxy, conf.id);
1965 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1966 file, linenum, proxy_type_str(curproxy), curproxy->id,
1967 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
1970 }
1971 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001972 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001973 else if (!strcmp(args[0], "description")) {
1974 int i, len=0;
1975 char *d;
1976
Cyril Bonté99ed3272010-01-24 23:29:44 +01001977 if (curproxy == &defproxy) {
1978 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1979 file, linenum, args[0]);
1980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
1983
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001984 if (!*args[1]) {
1985 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1986 file, linenum, args[0]);
1987 return -1;
1988 }
1989
1990 for(i=1; *args[i]; i++)
1991 len += strlen(args[i])+1;
1992
1993 d = (char *)calloc(1, len);
1994 curproxy->desc = d;
1995
1996 d += sprintf(d, "%s", args[1]);
1997 for(i=2; *args[i]; i++)
1998 d += sprintf(d, " %s", args[i]);
1999
2000 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2002 curproxy->state = PR_STSTOPPED;
2003 }
2004 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2005 curproxy->state = PR_STNEW;
2006 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002007 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2008 int cur_arg = 1;
2009 unsigned int set = 0;
2010
2011 while (*args[cur_arg]) {
2012 int u;
2013 if (strcmp(args[cur_arg], "all") == 0) {
2014 set = 0;
2015 break;
2016 }
2017 else if (strcmp(args[cur_arg], "odd") == 0) {
2018 set |= 0x55555555;
2019 }
2020 else if (strcmp(args[cur_arg], "even") == 0) {
2021 set |= 0xAAAAAAAA;
2022 }
2023 else {
2024 u = str2uic(args[cur_arg]);
2025 if (u < 1 || u > 32) {
2026 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2027 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002030 }
2031 if (u > global.nbproc) {
2032 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2033 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002035 }
2036 set |= 1 << (u - 1);
2037 }
2038 cur_arg++;
2039 }
2040 curproxy->bind_proc = set;
2041 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002042 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002043 if (curproxy == &defproxy) {
2044 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002047 }
2048
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002049 err = invalid_char(args[1]);
2050 if (err) {
2051 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2052 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002054 }
2055
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002056 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2057 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2058 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002061 }
2062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2064 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 if (*(args[1]) == 0) {
2070 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2071 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002072 err_code |= ERR_ALERT | ERR_FATAL;
2073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002075
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002076 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002077 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002078 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002079 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002080 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 curproxy->cookie_name = strdup(args[1]);
2082 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002083
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 cur_arg = 2;
2085 while (*(args[cur_arg])) {
2086 if (!strcmp(args[cur_arg], "rewrite")) {
2087 curproxy->options |= PR_O_COOK_RW;
2088 }
2089 else if (!strcmp(args[cur_arg], "indirect")) {
2090 curproxy->options |= PR_O_COOK_IND;
2091 }
2092 else if (!strcmp(args[cur_arg], "insert")) {
2093 curproxy->options |= PR_O_COOK_INS;
2094 }
2095 else if (!strcmp(args[cur_arg], "nocache")) {
2096 curproxy->options |= PR_O_COOK_NOC;
2097 }
2098 else if (!strcmp(args[cur_arg], "postonly")) {
2099 curproxy->options |= PR_O_COOK_POST;
2100 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002101 else if (!strcmp(args[cur_arg], "preserve")) {
2102 curproxy->options2 |= PR_O2_COOK_PSV;
2103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 else if (!strcmp(args[cur_arg], "prefix")) {
2105 curproxy->options |= PR_O_COOK_PFX;
2106 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002107 else if (!strcmp(args[cur_arg], "domain")) {
2108 if (!*args[cur_arg + 1]) {
2109 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2110 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002111 err_code |= ERR_ALERT | ERR_FATAL;
2112 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002113 }
2114
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002115 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002116 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002117 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2118 " dots nor does not start with a dot."
2119 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002121 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002122 }
2123
2124 err = invalid_domainchar(args[cur_arg + 1]);
2125 if (err) {
2126 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2127 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002130 }
2131
Willy Tarreau68a897b2009-12-03 23:28:34 +01002132 if (!curproxy->cookie_domain) {
2133 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2134 } else {
2135 /* one domain was already specified, add another one by
2136 * building the string which will be returned along with
2137 * the cookie.
2138 */
2139 char *new_ptr;
2140 int new_len = strlen(curproxy->cookie_domain) +
2141 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2142 new_ptr = malloc(new_len);
2143 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2144 free(curproxy->cookie_domain);
2145 curproxy->cookie_domain = new_ptr;
2146 }
Willy Tarreau31936852010-10-06 16:59:56 +02002147 cur_arg++;
2148 }
2149 else if (!strcmp(args[cur_arg], "maxidle")) {
2150 unsigned int maxidle;
2151 const char *res;
2152
2153 if (!*args[cur_arg + 1]) {
2154 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2155 file, linenum, args[cur_arg]);
2156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
2158 }
2159
2160 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2161 if (res) {
2162 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2163 file, linenum, *res, args[cur_arg]);
2164 err_code |= ERR_ALERT | ERR_FATAL;
2165 goto out;
2166 }
2167 curproxy->cookie_maxidle = maxidle;
2168 cur_arg++;
2169 }
2170 else if (!strcmp(args[cur_arg], "maxlife")) {
2171 unsigned int maxlife;
2172 const char *res;
2173
2174 if (!*args[cur_arg + 1]) {
2175 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2176 file, linenum, args[cur_arg]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
2181 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2182 if (res) {
2183 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2184 file, linenum, *res, args[cur_arg]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
2188 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002189 cur_arg++;
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002192 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 +02002193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }
2197 cur_arg++;
2198 }
2199 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2200 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2201 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
2204
2205 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2206 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2207 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002210
2211 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2212 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2213 file, linenum);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002217 else if (!strcmp(args[0], "persist")) { /* persist */
2218 if (*(args[1]) == 0) {
2219 Alert("parsing [%s:%d] : missing persist method.\n",
2220 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002223 }
2224
2225 if (!strncmp(args[1], "rdp-cookie", 10)) {
2226 curproxy->options2 |= PR_O2_RDPC_PRST;
2227
Emeric Brunb982a3d2010-01-04 15:45:53 +01002228 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002229 const char *beg, *end;
2230
2231 beg = args[1] + 11;
2232 end = strchr(beg, ')');
2233
2234 if (!end || end == beg) {
2235 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2236 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002237 err_code |= ERR_ALERT | ERR_FATAL;
2238 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002239 }
2240
2241 free(curproxy->rdp_cookie_name);
2242 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2243 curproxy->rdp_cookie_len = end-beg;
2244 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002245 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002246 free(curproxy->rdp_cookie_name);
2247 curproxy->rdp_cookie_name = strdup("msts");
2248 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2249 }
2250 else { /* syntax */
2251 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2252 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002253 err_code |= ERR_ALERT | ERR_FATAL;
2254 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002255 }
2256 }
2257 else {
2258 Alert("parsing [%s:%d] : unknown persist method.\n",
2259 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002262 }
2263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002265 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002267 if (curproxy == &defproxy) {
2268 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002277 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
2282 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002283 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 curproxy->appsession_name = strdup(args[1]);
2285 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2286 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002287 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2288 if (err) {
2289 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2290 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002291 err_code |= ERR_ALERT | ERR_FATAL;
2292 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002293 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002294 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002295
Willy Tarreau51041c72007-09-09 21:56:53 +02002296 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002298 err_code |= ERR_ALERT | ERR_ABORT;
2299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002300 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002301
2302 cur_arg = 6;
2303 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002304 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2305 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002306 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002307 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002308 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002309 } else if (!strcmp(args[cur_arg], "prefix")) {
2310 curproxy->options2 |= PR_O2_AS_PFX;
2311 } else if (!strcmp(args[cur_arg], "mode")) {
2312 if (!*args[cur_arg + 1]) {
2313 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2314 file, linenum, args[0], args[cur_arg]);
2315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
2317 }
2318
2319 cur_arg++;
2320 if (!strcmp(args[cur_arg], "query-string")) {
2321 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2322 curproxy->options2 |= PR_O2_AS_M_QS;
2323 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2324 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2325 curproxy->options2 |= PR_O2_AS_M_PP;
2326 } else {
2327 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002332 cur_arg++;
2333 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 } /* Url App Session */
2335 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002336 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002340 if (curproxy == &defproxy) {
2341 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
2344 }
2345
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 if (*(args[4]) == 0) {
2347 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2348 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002352 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 curproxy->capture_name = strdup(args[2]);
2354 curproxy->capture_namelen = strlen(curproxy->capture_name);
2355 curproxy->capture_len = atol(args[4]);
2356 if (curproxy->capture_len >= CAPTURE_LEN) {
2357 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2358 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->capture_len = CAPTURE_LEN - 1;
2361 }
2362 curproxy->to_log |= LW_COOKIE;
2363 }
2364 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2365 struct cap_hdr *hdr;
2366
2367 if (curproxy == &defproxy) {
2368 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 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
2372
2373 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2374 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002376 err_code |= ERR_ALERT | ERR_FATAL;
2377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 }
2379
2380 hdr = calloc(sizeof(struct cap_hdr), 1);
2381 hdr->next = curproxy->req_cap;
2382 hdr->name = strdup(args[3]);
2383 hdr->namelen = strlen(args[3]);
2384 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002385 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 hdr->index = curproxy->nb_req_cap++;
2387 curproxy->req_cap = hdr;
2388 curproxy->to_log |= LW_REQHDR;
2389 }
2390 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2391 struct cap_hdr *hdr;
2392
2393 if (curproxy == &defproxy) {
2394 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 +02002395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 }
2398
2399 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2400 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2401 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405 hdr = calloc(sizeof(struct cap_hdr), 1);
2406 hdr->next = curproxy->rsp_cap;
2407 hdr->name = strdup(args[3]);
2408 hdr->namelen = strlen(args[3]);
2409 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002410 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 hdr->index = curproxy->nb_rsp_cap++;
2412 curproxy->rsp_cap = hdr;
2413 curproxy->to_log |= LW_RSPHDR;
2414 }
2415 else {
2416 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
2421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 if (*(args[1]) == 0) {
2427 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 curproxy->conn_retries = atol(args[1]);
2433 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002434 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002435 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002436
2437 if (curproxy == &defproxy) {
2438 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
Willy Tarreauff011f22011-01-06 17:51:27 +01002443 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 +01002444 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2445 file, linenum, args[0]);
2446 err_code |= ERR_WARN;
2447 }
2448
Willy Tarreauff011f22011-01-06 17:51:27 +01002449 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002450
Willy Tarreauff011f22011-01-06 17:51:27 +01002451 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002452 err_code |= ERR_ALERT | ERR_ABORT;
2453 goto out;
2454 }
2455
Willy Tarreauff011f22011-01-06 17:51:27 +01002456 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2457 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002458 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002459 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002460 if (curproxy == &defproxy) {
2461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002464 }
2465
Willy Tarreauef6494c2010-01-28 17:12:36 +01002466 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002467 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002471 }
2472
Willy Tarreauef6494c2010-01-28 17:12:36 +01002473 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002474 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2475 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002478 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002479
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002480 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002481 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002483 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002484 struct redirect_rule *rule;
2485 int cur_arg;
2486 int type = REDIRECT_TYPE_NONE;
2487 int code = 302;
2488 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002489 char *cookie = NULL;
2490 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002491 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002492
Cyril Bonté99ed3272010-01-24 23:29:44 +01002493 if (curproxy == &defproxy) {
2494 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 cur_arg = 1;
2500 while (*(args[cur_arg])) {
2501 if (!strcmp(args[cur_arg], "location")) {
2502 if (!*args[cur_arg + 1]) {
2503 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2504 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002505 err_code |= ERR_ALERT | ERR_FATAL;
2506 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002507 }
2508
2509 type = REDIRECT_TYPE_LOCATION;
2510 cur_arg++;
2511 destination = args[cur_arg];
2512 }
2513 else if (!strcmp(args[cur_arg], "prefix")) {
2514 if (!*args[cur_arg + 1]) {
2515 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2516 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002519 }
2520
2521 type = REDIRECT_TYPE_PREFIX;
2522 cur_arg++;
2523 destination = args[cur_arg];
2524 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002525 else if (!strcmp(args[cur_arg], "set-cookie")) {
2526 if (!*args[cur_arg + 1]) {
2527 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2528 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
2530 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002531 }
2532
2533 cur_arg++;
2534 cookie = args[cur_arg];
2535 cookie_set = 1;
2536 }
2537 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2538 if (!*args[cur_arg + 1]) {
2539 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2540 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002543 }
2544
2545 cur_arg++;
2546 cookie = args[cur_arg];
2547 cookie_set = 0;
2548 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 else if (!strcmp(args[cur_arg],"code")) {
2550 if (!*args[cur_arg + 1]) {
2551 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2552 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002553 err_code |= ERR_ALERT | ERR_FATAL;
2554 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 }
2556 cur_arg++;
2557 code = atol(args[cur_arg]);
2558 if (code < 301 || code > 303) {
2559 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2560 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
2564 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002565 else if (!strcmp(args[cur_arg],"drop-query")) {
2566 flags |= REDIRECT_FLAG_DROP_QS;
2567 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002568 else if (!strcmp(args[cur_arg],"append-slash")) {
2569 flags |= REDIRECT_FLAG_APPEND_SLASH;
2570 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002571 else if (strcmp(args[cur_arg], "if") == 0 ||
2572 strcmp(args[cur_arg], "unless") == 0) {
2573 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2574 if (!cond) {
2575 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2576 file, linenum, args[0]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 break;
2581 }
2582 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002583 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 +02002584 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 }
2588 cur_arg++;
2589 }
2590
2591 if (type == REDIRECT_TYPE_NONE) {
2592 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2593 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002594 err_code |= ERR_ALERT | ERR_FATAL;
2595 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002596 }
2597
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002598 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2599 rule->cond = cond;
2600 rule->rdr_str = strdup(destination);
2601 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002602 if (cookie) {
2603 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002604 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002605 */
2606 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002607 if (cookie_set) {
2608 rule->cookie_str = malloc(rule->cookie_len + 10);
2609 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2610 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2611 rule->cookie_len += 9;
2612 } else {
2613 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002614 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002615 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2616 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002617 }
2618 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002619 rule->type = type;
2620 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002621 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002622 LIST_INIT(&rule->list);
2623 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002624 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2625 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002627 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 struct switching_rule *rule;
2629
Willy Tarreaub099aca2008-10-12 17:26:37 +02002630 if (curproxy == &defproxy) {
2631 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002634 }
2635
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002637 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638
2639 if (*(args[1]) == 0) {
2640 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002643 }
2644
Willy Tarreauef6494c2010-01-28 17:12:36 +01002645 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002646 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 }
2651
Willy Tarreauef6494c2010-01-28 17:12:36 +01002652 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002653 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002654 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002657 }
2658
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002659 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002660
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2662 rule->cond = cond;
2663 rule->be.name = strdup(args[1]);
2664 LIST_INIT(&rule->list);
2665 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2666 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002667 else if ((!strcmp(args[0], "force-persist")) ||
2668 (!strcmp(args[0], "ignore-persist"))) {
2669 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002670
2671 if (curproxy == &defproxy) {
2672 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2678 err_code |= ERR_WARN;
2679
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002681 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2682 file, linenum, args[0]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686
Willy Tarreauef6494c2010-01-28 17:12:36 +01002687 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002688 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2689 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
2692 }
2693
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002694 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002695
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002696 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002697 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002698 if (!strcmp(args[0], "force-persist")) {
2699 rule->type = PERSIST_TYPE_FORCE;
2700 } else {
2701 rule->type = PERSIST_TYPE_IGNORE;
2702 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002704 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002705 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002706 else if (!strcmp(args[0], "stick-table")) {
2707 int myidx = 1;
2708
Emeric Brun32da3c42010-09-23 18:39:19 +02002709 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 curproxy->table.type = (unsigned int)-1;
2711 while (*args[myidx]) {
2712 const char *err;
2713
2714 if (strcmp(args[myidx], "size") == 0) {
2715 myidx++;
2716 if (!*(args[myidx])) {
2717 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2718 file, linenum, args[myidx-1]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2723 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2724 file, linenum, *err, args[myidx-1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002728 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002729 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002730 else if (strcmp(args[myidx], "peers") == 0) {
2731 myidx++;
2732 if (!*(args[myidx])) {
2733 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2734 file, linenum, args[myidx-1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 curproxy->table.peers.name = strdup(args[myidx++]);
2739 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002740 else if (strcmp(args[myidx], "expire") == 0) {
2741 myidx++;
2742 if (!*(args[myidx])) {
2743 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2744 file, linenum, args[myidx-1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2749 if (err) {
2750 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2751 file, linenum, *err, args[myidx-1]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002756 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002757 }
2758 else if (strcmp(args[myidx], "nopurge") == 0) {
2759 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002760 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002761 }
2762 else if (strcmp(args[myidx], "type") == 0) {
2763 myidx++;
2764 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2765 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2766 file, linenum, args[myidx]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002770 /* myidx already points to next arg */
2771 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002772 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002773 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002774 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002775
2776 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 nw = args[myidx];
2778 while (*nw) {
2779 /* the "store" keyword supports a comma-separated list */
2780 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002781 sa = NULL; /* store arg */
2782 while (*nw && *nw != ',') {
2783 if (*nw == '(') {
2784 *nw = 0;
2785 sa = ++nw;
2786 while (*nw != ')') {
2787 if (!*nw) {
2788 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2789 file, linenum, args[0], cw);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793 nw++;
2794 }
2795 *nw = '\0';
2796 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002797 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002798 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 if (*nw)
2800 *nw++ = '\0';
2801 type = stktable_get_data_type(cw);
2802 if (type < 0) {
2803 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
Willy Tarreauac782882010-06-20 10:41:54 +02002808
2809 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2810 switch (err) {
2811 case PE_NONE: break;
2812 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002813 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2814 file, linenum, args[0], cw);
2815 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002816 break;
2817
2818 case PE_ARG_MISSING:
2819 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2820 file, linenum, args[0], cw);
2821 err_code |= ERR_ALERT | ERR_FATAL;
2822 goto out;
2823
2824 case PE_ARG_NOT_USED:
2825 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829
2830 default:
2831 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2832 file, linenum, args[0], cw);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002836 }
2837 myidx++;
2838 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002839 else {
2840 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2841 file, linenum, args[myidx]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002845 }
2846
2847 if (!curproxy->table.size) {
2848 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2849 file, linenum);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (curproxy->table.type == (unsigned int)-1) {
2855 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2856 file, linenum);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 }
2861 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002862 struct sticking_rule *rule;
2863 struct pattern_expr *expr;
2864 int myidx = 0;
2865 const char *name = NULL;
2866 int flags;
2867
2868 if (curproxy == &defproxy) {
2869 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
2872 }
2873
2874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2875 err_code |= ERR_WARN;
2876 goto out;
2877 }
2878
2879 myidx++;
2880 if ((strcmp(args[myidx], "store") == 0) ||
2881 (strcmp(args[myidx], "store-request") == 0)) {
2882 myidx++;
2883 flags = STK_IS_STORE;
2884 }
2885 else if (strcmp(args[myidx], "store-response") == 0) {
2886 myidx++;
2887 flags = STK_IS_STORE | STK_ON_RSP;
2888 }
2889 else if (strcmp(args[myidx], "match") == 0) {
2890 myidx++;
2891 flags = STK_IS_MATCH;
2892 }
2893 else if (strcmp(args[myidx], "on") == 0) {
2894 myidx++;
2895 flags = STK_IS_MATCH | STK_IS_STORE;
2896 }
2897 else {
2898 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
2901 }
2902
2903 if (*(args[myidx]) == 0) {
2904 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
2907 }
2908
Emeric Brun485479d2010-09-23 18:02:19 +02002909 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002911 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915
2916 if (flags & STK_ON_RSP) {
2917 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2918 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2919 file, linenum, args[0], expr->fetch->kw);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 } else {
2924 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2925 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2926 file, linenum, args[0], expr->fetch->kw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930 }
2931
2932 if (strcmp(args[myidx], "table") == 0) {
2933 myidx++;
2934 name = args[myidx++];
2935 }
2936
Willy Tarreauef6494c2010-01-28 17:12:36 +01002937 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2938 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002939 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2940 file, linenum, args[0]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002944 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002945 else if (*(args[myidx])) {
2946 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2947 file, linenum, args[0], args[myidx]);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
Emeric Brun97679e72010-09-23 17:56:44 +02002951 if (flags & STK_ON_RSP)
2952 err_code |= warnif_cond_requires_req(cond, file, linenum);
2953 else
2954 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002955
Emeric Brunb982a3d2010-01-04 15:45:53 +01002956 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2957 rule->cond = cond;
2958 rule->expr = expr;
2959 rule->flags = flags;
2960 rule->table.name = name ? strdup(name) : NULL;
2961 LIST_INIT(&rule->list);
2962 if (flags & STK_ON_RSP)
2963 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2964 else
2965 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2972 curproxy->uri_auth = NULL; /* we must detach from the default config */
2973
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002974 if (!*args[1]) {
2975 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002976 } else if (!strcmp(args[1], "admin")) {
2977 struct stats_admin_rule *rule;
2978
2979 if (curproxy == &defproxy) {
2980 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
2982 goto out;
2983 }
2984
2985 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2986 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2987 err_code |= ERR_ALERT | ERR_ABORT;
2988 goto out;
2989 }
2990
2991 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2992 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2993 file, linenum, args[0], args[1]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2998 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2999 file, linenum, args[0], args[1]);
3000 err_code |= ERR_ALERT | ERR_FATAL;
3001 goto out;
3002 }
3003
3004 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3005
3006 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3007 rule->cond = cond;
3008 LIST_INIT(&rule->list);
3009 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 } else if (!strcmp(args[1], "uri")) {
3011 if (*(args[2]) == 0) {
3012 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3016 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_ABORT;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 }
3020 } else if (!strcmp(args[1], "realm")) {
3021 if (*(args[2]) == 0) {
3022 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3026 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_ABORT;
3028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003030 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003031 unsigned interval;
3032
3033 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3034 if (err) {
3035 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3036 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003039 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_ABORT;
3042 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003043 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003044 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003045 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046
3047 if (curproxy == &defproxy) {
3048 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052
3053 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3054 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3055 err_code |= ERR_ALERT | ERR_ABORT;
3056 goto out;
3057 }
3058
Willy Tarreauff011f22011-01-06 17:51:27 +01003059 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3060 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003061 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3062 file, linenum, args[0]);
3063 err_code |= ERR_WARN;
3064 }
3065
Willy Tarreauff011f22011-01-06 17:51:27 +01003066 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003067
Willy Tarreauff011f22011-01-06 17:51:27 +01003068 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069 err_code |= ERR_ALERT | ERR_ABORT;
3070 goto out;
3071 }
3072
Willy Tarreauff011f22011-01-06 17:51:27 +01003073 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3074 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003075
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 } else if (!strcmp(args[1], "auth")) {
3077 if (*(args[2]) == 0) {
3078 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3082 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_ABORT;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 }
3086 } else if (!strcmp(args[1], "scope")) {
3087 if (*(args[2]) == 0) {
3088 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003091 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 }
3096 } else if (!strcmp(args[1], "enable")) {
3097 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003102 } else if (!strcmp(args[1], "hide-version")) {
3103 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3104 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003107 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003108 } else if (!strcmp(args[1], "show-legends")) {
3109 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3110 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3111 err_code |= ERR_ALERT | ERR_ABORT;
3112 goto out;
3113 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003114 } else if (!strcmp(args[1], "show-node")) {
3115
3116 if (*args[2]) {
3117 int i;
3118 char c;
3119
3120 for (i=0; args[2][i]; i++) {
3121 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003122 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3123 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003124 break;
3125 }
3126
3127 if (!i || args[2][i]) {
3128 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3129 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3130 file, linenum, args[0], args[1]);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134 }
3135
3136 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3137 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3138 err_code |= ERR_ALERT | ERR_ABORT;
3139 goto out;
3140 }
3141 } else if (!strcmp(args[1], "show-desc")) {
3142 char *desc = NULL;
3143
3144 if (*args[2]) {
3145 int i, len=0;
3146 char *d;
3147
3148 for(i=2; *args[i]; i++)
3149 len += strlen(args[i])+1;
3150
3151 desc = d = (char *)calloc(1, len);
3152
3153 d += sprintf(d, "%s", args[2]);
3154 for(i=3; *args[i]; i++)
3155 d += sprintf(d, " %s", args[i]);
3156 }
3157
3158 if (!*args[2] && !global.desc)
3159 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3160 file, linenum, args[1]);
3161 else {
3162 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3163 free(desc);
3164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3165 err_code |= ERR_ALERT | ERR_ABORT;
3166 goto out;
3167 }
3168 free(desc);
3169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003171stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003172 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 +01003173 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 }
3177 }
3178 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003179 int optnum;
3180
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003181 if (*(args[1]) == '\0') {
3182 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003187
3188 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3189 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003190 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3191 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3192 file, linenum, cfg_opts[optnum].name);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
Willy Tarreau93893792009-07-23 13:19:11 +02003196 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3197 err_code |= ERR_WARN;
3198 goto out;
3199 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003200
Willy Tarreau3842f002009-06-14 11:39:52 +02003201 curproxy->no_options &= ~cfg_opts[optnum].val;
3202 curproxy->options &= ~cfg_opts[optnum].val;
3203
3204 switch (kwm) {
3205 case KWM_STD:
3206 curproxy->options |= cfg_opts[optnum].val;
3207 break;
3208 case KWM_NO:
3209 curproxy->no_options |= cfg_opts[optnum].val;
3210 break;
3211 case KWM_DEF: /* already cleared */
3212 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003213 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003214
Willy Tarreau93893792009-07-23 13:19:11 +02003215 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003216 }
3217 }
3218
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003219 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3220 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003221 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3222 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3223 file, linenum, cfg_opts2[optnum].name);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
Willy Tarreau93893792009-07-23 13:19:11 +02003227 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3228 err_code |= ERR_WARN;
3229 goto out;
3230 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003231
Willy Tarreau3842f002009-06-14 11:39:52 +02003232 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3233 curproxy->options2 &= ~cfg_opts2[optnum].val;
3234
3235 switch (kwm) {
3236 case KWM_STD:
3237 curproxy->options2 |= cfg_opts2[optnum].val;
3238 break;
3239 case KWM_NO:
3240 curproxy->no_options2 |= cfg_opts2[optnum].val;
3241 break;
3242 case KWM_DEF: /* already cleared */
3243 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003244 }
Willy Tarreau93893792009-07-23 13:19:11 +02003245 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003246 }
3247 }
3248
Willy Tarreau3842f002009-06-14 11:39:52 +02003249 if (kwm != KWM_STD) {
3250 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003251 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003254 }
3255
Emeric Brun3a058f32009-06-30 18:26:00 +02003256 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 if (*(args[2]) != '\0') {
3261 if (!strcmp(args[2], "clf")) {
3262 curproxy->options2 |= PR_O2_CLFLOG;
3263 } else {
3264 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003267 }
3268 }
3269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 else if (!strcmp(args[1], "tcplog"))
3271 /* generate a detailed TCP log */
3272 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 else if (!strcmp(args[1], "tcpka")) {
3274 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277
3278 if (curproxy->cap & PR_CAP_FE)
3279 curproxy->options |= PR_O_TCP_CLI_KA;
3280 if (curproxy->cap & PR_CAP_BE)
3281 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
3283 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_WARN;
3286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003288 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003289 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003290 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003291 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003292 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003293 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003294 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003295 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (!*args[2]) { /* no argument */
3297 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3298 curproxy->check_len = strlen(DEF_CHECK_REQ);
3299 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003300 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003305 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 if (*args[4])
3307 reqlen += strlen(args[4]);
3308 else
3309 reqlen += strlen("HTTP/1.0");
3310
3311 curproxy->check_req = (char *)malloc(reqlen);
3312 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003313 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003315 }
3316 else if (!strcmp(args[1], "ssl-hello-chk")) {
3317 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003319 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003320
Willy Tarreaua534fea2008-08-03 12:19:50 +02003321 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003322 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003323 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003324 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003325 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003326 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003327 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003328 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
Willy Tarreau23677902007-05-08 23:50:35 +02003330 else if (!strcmp(args[1], "smtpchk")) {
3331 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003332 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003333 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003334 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003335 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003336 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003337 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003338 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003339 curproxy->options |= PR_O_SMTP_CHK;
3340
3341 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3342 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3343 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3344 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3345 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3346 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3347 curproxy->check_req = (char *)malloc(reqlen);
3348 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3349 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3350 } else {
3351 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3352 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3353 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3354 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3355 }
3356 }
3357 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003358 else if (!strcmp(args[1], "pgsql-check")) {
3359 /* use PostgreSQL request to check servers' health */
3360 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3361 err_code |= ERR_WARN;
3362
3363 free(curproxy->check_req);
3364 curproxy->check_req = NULL;
3365 curproxy->options &= ~PR_O_HTTP_CHK;
3366 curproxy->options &= ~PR_O_SMTP_CHK;
3367 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3368 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3369 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3370 curproxy->options2 |= PR_O2_PGSQL_CHK;
3371
3372 if (*(args[2])) {
3373 int cur_arg = 2;
3374
3375 while (*(args[cur_arg])) {
3376 if (strcmp(args[cur_arg], "user") == 0) {
3377 char * packet;
3378 uint32_t packet_len;
3379 uint32_t pv;
3380
3381 /* suboption header - needs additional argument for it */
3382 if (*(args[cur_arg+1]) == 0) {
3383 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3384 file, linenum, args[0], args[1], args[cur_arg]);
3385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3390 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3391 pv = htonl(0x30000); /* protocol version 3.0 */
3392
3393 packet = (char*) calloc(1, packet_len);
3394
3395 memcpy(packet + 4, &pv, 4);
3396
3397 /* copy "user" */
3398 memcpy(packet + 8, "user", 4);
3399
3400 /* copy username */
3401 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3402
3403 free(curproxy->check_req);
3404 curproxy->check_req = packet;
3405 curproxy->check_len = packet_len;
3406
3407 packet_len = htonl(packet_len);
3408 memcpy(packet, &packet_len, 4);
3409 cur_arg += 2;
3410 } else {
3411 /* unknown suboption - catchall */
3412 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3413 file, linenum, args[0], args[1]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417 } /* end while loop */
3418 }
3419 }
3420
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003421 else if (!strcmp(args[1], "mysql-check")) {
3422 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3424 err_code |= ERR_WARN;
3425
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003426 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003427 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003428 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003429 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003430 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003431 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003432 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003433 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003434
3435 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3436 * const char mysql40_client_auth_pkt[] = {
3437 * "\x0e\x00\x00" // packet length
3438 * "\x01" // packet number
3439 * "\x00\x00" // client capabilities
3440 * "\x00\x00\x01" // max packet
3441 * "haproxy\x00" // username (null terminated string)
3442 * "\x00" // filler (always 0x00)
3443 * "\x01\x00\x00" // packet length
3444 * "\x00" // packet number
3445 * "\x01" // COM_QUIT command
3446 * };
3447 */
3448
3449 if (*(args[2])) {
3450 int cur_arg = 2;
3451
3452 while (*(args[cur_arg])) {
3453 if (strcmp(args[cur_arg], "user") == 0) {
3454 char *mysqluser;
3455 int packetlen, reqlen, userlen;
3456
3457 /* suboption header - needs additional argument for it */
3458 if (*(args[cur_arg+1]) == 0) {
3459 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3460 file, linenum, args[0], args[1], args[cur_arg]);
3461 err_code |= ERR_ALERT | ERR_FATAL;
3462 goto out;
3463 }
3464 mysqluser = args[cur_arg + 1];
3465 userlen = strlen(mysqluser);
3466 packetlen = userlen + 7;
3467 reqlen = packetlen + 9;
3468
3469 free(curproxy->check_req);
3470 curproxy->check_req = (char *)calloc(1, reqlen);
3471 curproxy->check_len = reqlen;
3472
3473 snprintf(curproxy->check_req, 4, "%c%c%c",
3474 ((unsigned char) packetlen & 0xff),
3475 ((unsigned char) (packetlen >> 8) & 0xff),
3476 ((unsigned char) (packetlen >> 16) & 0xff));
3477
3478 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003479 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003480 curproxy->check_req[8] = 1;
3481 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3482 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3483 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3484 cur_arg += 2;
3485 } else {
3486 /* unknown suboption - catchall */
3487 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3488 file, linenum, args[0], args[1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492 } /* end while loop */
3493 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003494 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003495 else if (!strcmp(args[1], "ldap-check")) {
3496 /* use LDAP request to check servers' health */
3497 free(curproxy->check_req);
3498 curproxy->check_req = NULL;
3499 curproxy->options &= ~PR_O_HTTP_CHK;
3500 curproxy->options &= ~PR_O_SMTP_CHK;
3501 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3502 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003503 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003504 curproxy->options2 |= PR_O2_LDAP_CHK;
3505
3506 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3507 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3508 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3509 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003510 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003511 int cur_arg;
3512
3513 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3514 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003515 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003516
3517 curproxy->options |= PR_O_FWDFOR;
3518
3519 free(curproxy->fwdfor_hdr_name);
3520 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3521 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3522
3523 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3524 cur_arg = 2;
3525 while (*(args[cur_arg])) {
3526 if (!strcmp(args[cur_arg], "except")) {
3527 /* suboption except - needs additional argument for it */
3528 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3529 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3530 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003533 }
3534 /* flush useless bits */
3535 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003536 cur_arg += 2;
3537 } else if (!strcmp(args[cur_arg], "header")) {
3538 /* suboption header - needs additional argument for it */
3539 if (*(args[cur_arg+1]) == 0) {
3540 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3541 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003542 err_code |= ERR_ALERT | ERR_FATAL;
3543 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003544 }
3545 free(curproxy->fwdfor_hdr_name);
3546 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3547 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3548 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003549 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003550 /* unknown suboption - catchall */
3551 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3552 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003555 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003556 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003557 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003558 else if (!strcmp(args[1], "originalto")) {
3559 int cur_arg;
3560
3561 /* insert x-original-to field, but not for the IP address listed as an except.
3562 * set default options (ie: bitfield, header name, etc)
3563 */
3564
3565 curproxy->options |= PR_O_ORGTO;
3566
3567 free(curproxy->orgto_hdr_name);
3568 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3569 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3570
3571 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3572 cur_arg = 2;
3573 while (*(args[cur_arg])) {
3574 if (!strcmp(args[cur_arg], "except")) {
3575 /* suboption except - needs additional argument for it */
3576 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3577 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3578 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003581 }
3582 /* flush useless bits */
3583 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3584 cur_arg += 2;
3585 } else if (!strcmp(args[cur_arg], "header")) {
3586 /* suboption header - needs additional argument for it */
3587 if (*(args[cur_arg+1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3589 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_FATAL;
3591 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003592 }
3593 free(curproxy->orgto_hdr_name);
3594 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3595 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3596 cur_arg += 2;
3597 } else {
3598 /* unknown suboption - catchall */
3599 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3600 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003603 }
3604 } /* end while loop */
3605 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 else {
3607 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 }
Willy Tarreau93893792009-07-23 13:19:11 +02003611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003613 else if (!strcmp(args[0], "default_backend")) {
3614 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003616
3617 if (*(args[1]) == 0) {
3618 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_ALERT | ERR_FATAL;
3620 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003621 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003622 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003623 curproxy->defbe.name = strdup(args[1]);
3624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003625 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003628
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003629 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 /* enable reconnections to dispatch */
3633 curproxy->options |= PR_O_REDISP;
3634 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003635 else if (!strcmp(args[0], "http-check")) {
3636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003638
3639 if (strcmp(args[1], "disable-on-404") == 0) {
3640 /* enable a graceful server shutdown on an HTTP 404 response */
3641 curproxy->options |= PR_O_DISABLE404;
3642 }
Willy Tarreauef781042010-01-27 11:53:01 +01003643 else if (strcmp(args[1], "send-state") == 0) {
3644 /* enable emission of the apparent state of a server in HTTP checks */
3645 curproxy->options2 |= PR_O2_CHK_SNDST;
3646 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003647 else if (strcmp(args[1], "expect") == 0) {
3648 const char *ptr_arg;
3649 int cur_arg;
3650
3651 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3652 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 cur_arg = 2;
3658 /* consider exclamation marks, sole or at the beginning of a word */
3659 while (*(ptr_arg = args[cur_arg])) {
3660 while (*ptr_arg == '!') {
3661 curproxy->options2 ^= PR_O2_EXP_INV;
3662 ptr_arg++;
3663 }
3664 if (*ptr_arg)
3665 break;
3666 cur_arg++;
3667 }
3668 /* now ptr_arg points to the beginning of a word past any possible
3669 * exclamation mark, and cur_arg is the argument which holds this word.
3670 */
3671 if (strcmp(ptr_arg, "status") == 0) {
3672 if (!*(args[cur_arg + 1])) {
3673 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3674 file, linenum, args[0], args[1], ptr_arg);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678 curproxy->options2 |= PR_O2_EXP_STS;
3679 curproxy->expect_str = strdup(args[cur_arg + 1]);
3680 }
3681 else if (strcmp(ptr_arg, "string") == 0) {
3682 if (!*(args[cur_arg + 1])) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3684 file, linenum, args[0], args[1], ptr_arg);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688 curproxy->options2 |= PR_O2_EXP_STR;
3689 curproxy->expect_str = strdup(args[cur_arg + 1]);
3690 }
3691 else if (strcmp(ptr_arg, "rstatus") == 0) {
3692 if (!*(args[cur_arg + 1])) {
3693 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3694 file, linenum, args[0], args[1], ptr_arg);
3695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698 curproxy->options2 |= PR_O2_EXP_RSTS;
3699 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3700 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3701 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3702 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3703 err_code |= ERR_ALERT | ERR_FATAL;
3704 goto out;
3705 }
3706 }
3707 else if (strcmp(ptr_arg, "rstring") == 0) {
3708 if (!*(args[cur_arg + 1])) {
3709 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3710 file, linenum, args[0], args[1], ptr_arg);
3711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
3713 }
3714 curproxy->options2 |= PR_O2_EXP_RSTR;
3715 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3716 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3717 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3718 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 }
3723 else {
3724 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3725 file, linenum, args[0], args[1], ptr_arg);
3726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
3728 }
3729 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003730 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003731 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003734 }
3735 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003736 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003737 if (curproxy == &defproxy) {
3738 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003741 }
3742
Willy Tarreaub80c2302007-11-30 20:51:32 +01003743 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003745
3746 if (strcmp(args[1], "fail") == 0) {
3747 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003748 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003749 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3750 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 }
3754
Willy Tarreauef6494c2010-01-28 17:12:36 +01003755 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003756 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3757 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_ALERT | ERR_FATAL;
3759 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003760 }
3761 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3762 }
3763 else {
3764 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003767 }
3768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769#ifdef TPROXY
3770 else if (!strcmp(args[0], "transparent")) {
3771 /* enable transparent proxy connections */
3772 curproxy->options |= PR_O_TRANSP;
3773 }
3774#endif
3775 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 if (*(args[1]) == 0) {
3780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
3784 curproxy->maxconn = atol(args[1]);
3785 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003786 else if (!strcmp(args[0], "backlog")) { /* backlog */
3787 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003789
3790 if (*(args[1]) == 0) {
3791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003794 }
3795 curproxy->backlog = atol(args[1]);
3796 }
Willy Tarreau86034312006-12-29 00:10:33 +01003797 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003800
Willy Tarreau86034312006-12-29 00:10:33 +01003801 if (*(args[1]) == 0) {
3802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003805 }
3806 curproxy->fullconn = atol(args[1]);
3807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3809 if (*(args[1]) == 0) {
3810 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_ALERT | ERR_FATAL;
3812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003814 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3815 if (err) {
3816 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3817 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003820 }
3821 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003822 }
3823 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003824 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003830 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003832
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 if (strchr(args[1], ':') == NULL) {
3834 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003838 sk = str2sa(args[1]);
3839 if (!sk) {
3840 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
3843 }
3844 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003845 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 }
3847 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003848 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003850
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003851 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003852 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3853 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003858 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3860 err_code |= ERR_WARN;
3861
3862 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3863 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3864 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3865 }
3866 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3868 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3869 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003870 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3871 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3872 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3873 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003874 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003875 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003876 err_code |= ERR_ALERT | ERR_FATAL;
3877 goto out;
3878 }
3879 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003882 char *rport, *raddr;
3883 short realport = 0;
3884 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003886 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893
3894 if (!*args[2]) {
3895 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003900
3901 err = invalid_char(args[1]);
3902 if (err) {
3903 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3904 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003907 }
3908
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003909 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003910 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003911
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003912 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3913 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3914 err_code |= ERR_ALERT | ERR_ABORT;
3915 goto out;
3916 }
3917
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003918 /* the servers are linked backwards first */
3919 newsrv->next = curproxy->srv;
3920 curproxy->srv = newsrv;
3921 newsrv->proxy = curproxy;
3922 newsrv->conf.file = file;
3923 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924
Simon Hormanaf514952011-06-21 14:34:57 +09003925 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 LIST_INIT(&newsrv->pendconns);
3927 do_check = 0;
3928 newsrv->state = SRV_RUNNING; /* early server setup */
3929 newsrv->last_change = now.tv_sec;
3930 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003932 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003933 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934 * - IP: => port=+0, relative
3935 * - IP:N => port=N, absolute
3936 * - IP:+N => port=+N, relative
3937 * - IP:-N => port=-N, relative
3938 */
3939 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003940 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003941 if (rport) {
3942 *rport++ = 0;
3943 realport = atol(rport);
3944 if (!isdigit((unsigned char)*rport))
3945 newsrv->state |= SRV_MAPPORTS;
3946 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948
Willy Tarreaufab5a432011-03-04 15:31:53 +01003949 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003950 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003951 if (!sk) {
3952 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003957
3958 switch (newsrv->addr.ss_family) {
3959 case AF_INET:
3960 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3961 break;
3962 case AF_INET6:
3963 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3964 break;
3965 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003966
3967 newsrv->check_port = curproxy->defsrv.check_port;
3968 newsrv->inter = curproxy->defsrv.inter;
3969 newsrv->fastinter = curproxy->defsrv.fastinter;
3970 newsrv->downinter = curproxy->defsrv.downinter;
3971 newsrv->rise = curproxy->defsrv.rise;
3972 newsrv->fall = curproxy->defsrv.fall;
3973 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3974 newsrv->minconn = curproxy->defsrv.minconn;
3975 newsrv->maxconn = curproxy->defsrv.maxconn;
3976 newsrv->slowstart = curproxy->defsrv.slowstart;
3977 newsrv->onerror = curproxy->defsrv.onerror;
3978 newsrv->consecutive_errors_limit
3979 = curproxy->defsrv.consecutive_errors_limit;
3980 newsrv->uweight = newsrv->iweight
3981 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003983 newsrv->curfd = -1; /* no health-check in progress */
3984 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003986 cur_arg = 3;
3987 } else {
3988 newsrv = &curproxy->defsrv;
3989 cur_arg = 1;
3990 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003991
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003993 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003994 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003995
3996 if (!*args[cur_arg + 1]) {
3997 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3998 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004001 }
4002
4003 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004004 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004005
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004006 if (newsrv->puid <= 0) {
4007 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004008 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004011 }
4012
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004013 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4014 if (node) {
4015 struct server *target = container_of(node, struct server, conf.id);
4016 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4017 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004022 cur_arg += 2;
4023 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 newsrv->cookie = strdup(args[cur_arg + 1]);
4026 newsrv->cklen = strlen(args[cur_arg + 1]);
4027 cur_arg += 2;
4028 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004030 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4031 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4032 cur_arg += 2;
4033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004035 if (!*args[cur_arg + 1]) {
4036 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4037 file, linenum, args[cur_arg]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004043 if (newsrv->rise <= 0) {
4044 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4045 file, linenum, args[cur_arg]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049
Willy Tarreau96839092010-03-29 10:02:24 +02004050 if (newsrv->health)
4051 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 cur_arg += 2;
4053 }
4054 else if (!strcmp(args[cur_arg], "fall")) {
4055 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004056
4057 if (!*args[cur_arg + 1]) {
4058 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4059 file, linenum, args[cur_arg]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
4064 if (newsrv->fall <= 0) {
4065 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4066 file, linenum, args[cur_arg]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 cur_arg += 2;
4072 }
4073 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004074 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4075 if (err) {
4076 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4077 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004080 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004081 if (val <= 0) {
4082 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4083 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004086 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004087 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004088 cur_arg += 2;
4089 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004090 else if (!strcmp(args[cur_arg], "fastinter")) {
4091 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4092 if (err) {
4093 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4094 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004097 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004098 if (val <= 0) {
4099 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4100 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004103 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004104 newsrv->fastinter = val;
4105 cur_arg += 2;
4106 }
4107 else if (!strcmp(args[cur_arg], "downinter")) {
4108 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4109 if (err) {
4110 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4111 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004114 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004115 if (val <= 0) {
4116 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4117 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004120 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004121 newsrv->downinter = val;
4122 cur_arg += 2;
4123 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004124 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004125 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004126 if (!sk) {
4127 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004132 cur_arg += 2;
4133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 else if (!strcmp(args[cur_arg], "port")) {
4135 newsrv->check_port = atol(args[cur_arg + 1]);
4136 cur_arg += 2;
4137 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 newsrv->state |= SRV_BACKUP;
4140 cur_arg ++;
4141 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4143 newsrv->state |= SRV_SEND_PROXY;
4144 cur_arg ++;
4145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 else if (!strcmp(args[cur_arg], "weight")) {
4147 int w;
4148 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004149 if (w < 0 || w > 256) {
4150 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004155 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "minconn")) {
4159 newsrv->minconn = atol(args[cur_arg + 1]);
4160 cur_arg += 2;
4161 }
4162 else if (!strcmp(args[cur_arg], "maxconn")) {
4163 newsrv->maxconn = atol(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004166 else if (!strcmp(args[cur_arg], "maxqueue")) {
4167 newsrv->maxqueue = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004170 else if (!strcmp(args[cur_arg], "slowstart")) {
4171 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004172 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004173 if (err) {
4174 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4175 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004178 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004179 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004180 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4181 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004185 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004186 cur_arg += 2;
4187 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004188 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004189
4190 if (!*args[cur_arg + 1]) {
4191 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4192 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004195 }
4196
4197 newsrv->trackit = strdup(args[cur_arg + 1]);
4198
4199 cur_arg += 2;
4200 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004201 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 global.maxsock++;
4203 do_check = 1;
4204 cur_arg += 1;
4205 }
Willy Tarreau96839092010-03-29 10:02:24 +02004206 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4207 newsrv->state |= SRV_MAINTAIN;
4208 newsrv->state &= ~SRV_RUNNING;
4209 newsrv->health = 0;
4210 cur_arg += 1;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004213 if (!strcmp(args[cur_arg + 1], "none"))
4214 newsrv->observe = HANA_OBS_NONE;
4215 else if (!strcmp(args[cur_arg + 1], "layer4"))
4216 newsrv->observe = HANA_OBS_LAYER4;
4217 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4218 if (curproxy->mode != PR_MODE_HTTP) {
4219 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4220 file, linenum, args[cur_arg + 1]);
4221 err_code |= ERR_ALERT;
4222 }
4223 newsrv->observe = HANA_OBS_LAYER7;
4224 }
4225 else {
4226 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004227 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004228 file, linenum, args[cur_arg], args[cur_arg + 1]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
4233 cur_arg += 2;
4234 }
4235 else if (!strcmp(args[cur_arg], "on-error")) {
4236 if (!strcmp(args[cur_arg + 1], "fastinter"))
4237 newsrv->onerror = HANA_ONERR_FASTINTER;
4238 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4239 newsrv->onerror = HANA_ONERR_FAILCHK;
4240 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4241 newsrv->onerror = HANA_ONERR_SUDDTH;
4242 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4243 newsrv->onerror = HANA_ONERR_MARKDWN;
4244 else {
4245 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004246 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004247 file, linenum, args[cur_arg], args[cur_arg + 1]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
4252 cur_arg += 2;
4253 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004254 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4255 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4256 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4257 else {
4258 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4259 file, linenum, args[cur_arg], args[cur_arg + 1]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 cur_arg += 2;
4265 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004266 else if (!strcmp(args[cur_arg], "error-limit")) {
4267 if (!*args[cur_arg + 1]) {
4268 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4269 file, linenum, args[cur_arg]);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273
4274 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4275
4276 if (newsrv->consecutive_errors_limit <= 0) {
4277 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4278 file, linenum, args[cur_arg]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004282 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004283 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004284 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004285 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004286 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004287
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004289#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004290 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004291 file, linenum, "source", "usesrc");
4292#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004293 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004295#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
4299 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004300 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4301 if (!sk) {
4302 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004307
4308 if (port_low != port_high) {
4309 int i;
4310 if (port_low <= 0 || port_low > 65535 ||
4311 port_high <= 0 || port_high > 65535 ||
4312 port_low > port_high) {
4313 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4314 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004317 }
4318 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4319 for (i = 0; i < newsrv->sport_range->size; i++)
4320 newsrv->sport_range->ports[i] = port_low + i;
4321 }
4322
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004324 while (*(args[cur_arg])) {
4325 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004326#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4327#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4329 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4330 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004334#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004336 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004340 }
4341 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004342 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004343 newsrv->state |= SRV_TPROXY_CLI;
4344 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004345 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004346 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004347 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4348 char *name, *end;
4349
4350 name = args[cur_arg+1] + 7;
4351 while (isspace(*name))
4352 name++;
4353
4354 end = name;
4355 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4356 end++;
4357
4358 newsrv->state &= ~SRV_TPROXY_MASK;
4359 newsrv->state |= SRV_TPROXY_DYN;
4360 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4361 newsrv->bind_hdr_len = end - name;
4362 memcpy(newsrv->bind_hdr_name, name, end - name);
4363 newsrv->bind_hdr_name[end-name] = '\0';
4364 newsrv->bind_hdr_occ = -1;
4365
4366 /* now look for an occurrence number */
4367 while (isspace(*end))
4368 end++;
4369 if (*end == ',') {
4370 end++;
4371 name = end;
4372 if (*end == '-')
4373 end++;
4374 while (isdigit(*end))
4375 end++;
4376 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4377 }
4378
4379 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4380 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4381 " occurrences values smaller than %d.\n",
4382 file, linenum, MAX_HDR_HISTORY);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004387 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004388 if (!sk) {
4389 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 }
4396 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004397#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004399#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 cur_arg += 2;
4401 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004402#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004404 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4408 } /* "usesrc" */
4409
4410 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4411#ifdef SO_BINDTODEVICE
4412 if (!*args[cur_arg + 1]) {
4413 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 }
4418 if (newsrv->iface_name)
4419 free(newsrv->iface_name);
4420
4421 newsrv->iface_name = strdup(args[cur_arg + 1]);
4422 newsrv->iface_len = strlen(newsrv->iface_name);
4423 global.last_checks |= LSTCHK_NETADM;
4424#else
4425 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4426 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004429#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 cur_arg += 2;
4431 continue;
4432 }
4433 /* this keyword in not an option of "source" */
4434 break;
4435 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004437 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004438 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4439 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004444 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004445 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 +01004446 file, linenum, newsrv->id);
4447 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004448 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 +01004449 file, linenum);
4450
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 }
4454 }
4455
4456 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004457 if (newsrv->trackit) {
4458 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4459 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004462 }
4463
David du Colombier6f5ccb12011-03-10 22:26:24 +01004464 switch (newsrv->check_addr.ss_family) {
4465 case AF_INET:
4466 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4467 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4468 break;
4469 case AF_INET6:
4470 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4471 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4472 break;
4473 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004474
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4476 newsrv->check_port = realport; /* by default */
4477 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004478 /* not yet valid, because no port was set on
4479 * the server either. We'll check if we have
4480 * a known port on the first listener.
4481 */
4482 struct listener *l;
4483 l = curproxy->listen;
4484 if (l) {
4485 int port;
4486 port = (l->addr.ss_family == AF_INET6)
4487 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4488 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4489 newsrv->check_port = port;
4490 }
4491 }
4492 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4494 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004498
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004499 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004500 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004501 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4502 err_code |= ERR_ALERT | ERR_ABORT;
4503 goto out;
4504 }
4505
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004506 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 newsrv->state |= SRV_CHECKED;
4508 }
4509
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004510 if (!defsrv) {
4511 if (newsrv->state & SRV_BACKUP)
4512 curproxy->srv_bck++;
4513 else
4514 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004515
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004516 newsrv->prev_state = newsrv->state;
4517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
4519 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004520 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 int facility;
4522
4523 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4524 curproxy->logfac1 = global.logfac1;
4525 curproxy->logsrv1 = global.logsrv1;
4526 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004527 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004528 curproxy->logfac2 = global.logfac2;
4529 curproxy->logsrv2 = global.logsrv2;
4530 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004531 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 }
4533 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004534 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535
4536 facility = get_log_facility(args[2]);
4537 if (facility < 0) {
4538 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4539 exit(1);
4540 }
4541
4542 level = 7; /* max syslog level = debug */
4543 if (*(args[3])) {
4544 level = get_log_level(args[3]);
4545 if (level < 0) {
4546 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4547 exit(1);
4548 }
4549 }
4550
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004551 minlvl = 0; /* limit syslog level to this level (emerg) */
4552 if (*(args[4])) {
4553 minlvl = get_log_level(args[4]);
4554 if (level < 0) {
4555 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4556 exit(1);
4557 }
4558 }
4559
Robert Tsai81ae1952007-12-05 10:47:29 +01004560 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004561 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004562 if (!sk) {
4563 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004564 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004568 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004569 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004570 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004571 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004572 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004576 logsrv.addr = *sk;
4577 if (!get_host_port(&logsrv.addr))
4578 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580
4581 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004582 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 curproxy->logfac1 = facility;
4584 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004585 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 }
4587 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004588 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 curproxy->logfac2 = facility;
4590 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004591 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
4593 else {
4594 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 }
4598 }
4599 else {
4600 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4601 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 }
4605 }
4606 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004607 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004608 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004609
Willy Tarreau977b8e42006-12-29 14:19:17 +01004610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004612
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004614 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4615 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004619
4620 /* we must first clear any optional default setting */
4621 curproxy->options &= ~PR_O_TPXY_MASK;
4622 free(curproxy->iface_name);
4623 curproxy->iface_name = NULL;
4624 curproxy->iface_len = 0;
4625
Willy Tarreaud5191e72010-02-09 20:50:45 +01004626 sk = str2sa(args[1]);
4627 if (!sk) {
4628 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631 }
4632 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004634
4635 cur_arg = 2;
4636 while (*(args[cur_arg])) {
4637 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004638#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4639#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004640 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4641 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4642 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004645 }
4646#endif
4647 if (!*args[cur_arg + 1]) {
4648 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4649 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004652 }
4653
4654 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004655 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004656 curproxy->options |= PR_O_TPXY_CLI;
4657 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004658 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004659 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004660 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4661 char *name, *end;
4662
4663 name = args[cur_arg+1] + 7;
4664 while (isspace(*name))
4665 name++;
4666
4667 end = name;
4668 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4669 end++;
4670
4671 curproxy->options &= ~PR_O_TPXY_MASK;
4672 curproxy->options |= PR_O_TPXY_DYN;
4673 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4674 curproxy->bind_hdr_len = end - name;
4675 memcpy(curproxy->bind_hdr_name, name, end - name);
4676 curproxy->bind_hdr_name[end-name] = '\0';
4677 curproxy->bind_hdr_occ = -1;
4678
4679 /* now look for an occurrence number */
4680 while (isspace(*end))
4681 end++;
4682 if (*end == ',') {
4683 end++;
4684 name = end;
4685 if (*end == '-')
4686 end++;
4687 while (isdigit(*end))
4688 end++;
4689 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4690 }
4691
4692 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4693 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4694 " occurrences values smaller than %d.\n",
4695 file, linenum, MAX_HDR_HISTORY);
4696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
4698 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004700 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004701 if (!sk) {
4702 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
4705 }
4706 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004707 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004708 }
4709 global.last_checks |= LSTCHK_NETADM;
4710#if !defined(CONFIG_HAP_LINUX_TPROXY)
4711 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004712#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004713#else /* no TPROXY support */
4714 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004715 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004718#endif
4719 cur_arg += 2;
4720 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004721 }
4722
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004723 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4724#ifdef SO_BINDTODEVICE
4725 if (!*args[cur_arg + 1]) {
4726 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4727 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004730 }
4731 if (curproxy->iface_name)
4732 free(curproxy->iface_name);
4733
4734 curproxy->iface_name = strdup(args[cur_arg + 1]);
4735 curproxy->iface_len = strlen(curproxy->iface_name);
4736 global.last_checks |= LSTCHK_NETADM;
4737#else
4738 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4739 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004742#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004743 cur_arg += 2;
4744 continue;
4745 }
4746 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4747 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004752 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4753 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4754 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765
4766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
4779 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4781 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 }
4786 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
4793 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4795 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004796 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004800 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4802 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004805 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004806 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004807 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4809 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004810 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004812 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004813 }
4814 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4816 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004817 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004819 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4824 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828
4829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
4835 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004838 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
4842 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4844 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004845 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004846 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
4849 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4851 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004852 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004853 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
4856 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004857 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4858 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004859 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004860 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004863 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004864 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4865 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004866 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004867 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004868 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004871 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004872
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 if (curproxy == &defproxy) {
4874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004878 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004879 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 if (*(args[1]) == 0) {
4882 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004886
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004887 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4889 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4890 file, linenum, args[0]);
4891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
4894 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4895 }
4896 else if (*args[2]) {
4897 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4898 file, linenum, args[0], args[2]);
4899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
4901 }
4902
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004903 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004904 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004905 wl->s = strdup(args[1]);
4906 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004907 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004916
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4918 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004919 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4925 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004926 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4932 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004933 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_ALERT | ERR_FATAL;
4942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4946 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004947 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4953 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004954 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4960 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004961 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
4965 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004966 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004967
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 if (curproxy == &defproxy) {
4969 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004973 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004974 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975
Willy Tarreaubaaee002006-06-26 02:48:02 +02004976 if (*(args[1]) == 0) {
4977 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
4981
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004982 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4983 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4984 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4985 file, linenum, args[0]);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989 err_code |= warnif_cond_requires_req(cond, file, linenum);
4990 }
4991 else if (*args[2]) {
4992 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4993 file, linenum, args[0], args[2]);
4994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004998 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004999 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005000 wl->s = strdup(args[1]);
5001 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
5003 else if (!strcmp(args[0], "errorloc") ||
5004 !strcmp(args[0], "errorloc302") ||
5005 !strcmp(args[0], "errorloc303")) { /* error location */
5006 int errnum, errlen;
5007 char *err;
5008
Willy Tarreau977b8e42006-12-29 14:19:17 +01005009 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005011
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005013 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
5017
5018 errnum = atol(args[1]);
5019 if (!strcmp(args[0], "errorloc303")) {
5020 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5021 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5022 } else {
5023 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5024 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5025 }
5026
Willy Tarreau0f772532006-12-23 20:51:41 +01005027 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5028 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005029 chunk_destroy(&curproxy->errmsg[rc]);
5030 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005031 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005034
5035 if (rc >= HTTP_ERR_SIZE) {
5036 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5037 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005038 free(err);
5039 }
5040 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005041 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5042 int errnum, errlen, fd;
5043 char *err;
5044 struct stat stat;
5045
5046 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005048
5049 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005050 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005053 }
5054
5055 fd = open(args[2], O_RDONLY);
5056 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5057 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5058 file, linenum, args[2], args[1]);
5059 if (fd >= 0)
5060 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005063 }
5064
Willy Tarreau27a674e2009-08-17 07:23:33 +02005065 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005066 errlen = stat.st_size;
5067 } else {
5068 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005069 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005070 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005071 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005072 }
5073
5074 err = malloc(errlen); /* malloc() must succeed during parsing */
5075 errnum = read(fd, err, errlen);
5076 if (errnum != errlen) {
5077 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5078 file, linenum, args[2], args[1]);
5079 close(fd);
5080 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005083 }
5084 close(fd);
5085
5086 errnum = atol(args[1]);
5087 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5088 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005089 chunk_destroy(&curproxy->errmsg[rc]);
5090 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005091 break;
5092 }
5093 }
5094
5095 if (rc >= HTTP_ERR_SIZE) {
5096 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5097 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005099 free(err);
5100 }
5101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005103 struct cfg_kw_list *kwl;
5104 int index;
5105
5106 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5107 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5108 if (kwl->kw[index].section != CFG_LISTEN)
5109 continue;
5110 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5111 /* prepare error message just in case */
5112 snprintf(trash, sizeof(trash),
5113 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005114 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5115 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005116 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005119 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005120 else if (rc > 0) {
5121 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005122 err_code |= ERR_WARN;
5123 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005124 }
Willy Tarreau93893792009-07-23 13:19:11 +02005125 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005126 }
5127 }
5128 }
5129
Willy Tarreau6daf3432008-01-22 16:44:08 +01005130 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreau93893792009-07-23 13:19:11 +02005134 out:
5135 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005136}
5137
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005138int
5139cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5140{
5141
5142 int err_code = 0;
5143 const char *err;
5144
5145 if (!strcmp(args[0], "userlist")) { /* new userlist */
5146 struct userlist *newul;
5147
5148 if (!*args[1]) {
5149 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5150 file, linenum, args[0]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154
5155 err = invalid_char(args[1]);
5156 if (err) {
5157 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5158 file, linenum, *err, args[0], args[1]);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
5162
5163 for (newul = userlist; newul; newul = newul->next)
5164 if (!strcmp(newul->name, args[1])) {
5165 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5166 file, linenum, args[1]);
5167 err_code |= ERR_WARN;
5168 goto out;
5169 }
5170
5171 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5172 if (!newul) {
5173 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5174 err_code |= ERR_ALERT | ERR_ABORT;
5175 goto out;
5176 }
5177
5178 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5179 newul->name = strdup(args[1]);
5180
5181 if (!newul->groupusers | !newul->name) {
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->next = userlist;
5188 userlist = newul;
5189
5190 } else if (!strcmp(args[0], "group")) { /* new group */
5191 int cur_arg, i;
5192 const char *err;
5193
5194 if (!*args[1]) {
5195 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5196 file, linenum, args[0]);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
5200
5201 err = invalid_char(args[1]);
5202 if (err) {
5203 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5204 file, linenum, *err, args[0], args[1]);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 for(i = 0; i < userlist->grpcnt; i++)
5210 if (!strcmp(userlist->groups[i], args[1])) {
5211 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5212 file, linenum, args[1], userlist->name);
5213 err_code |= ERR_ALERT;
5214 goto out;
5215 }
5216
5217 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5218 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5219 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
5222 }
5223
5224 cur_arg = 2;
5225
5226 while (*args[cur_arg]) {
5227 if (!strcmp(args[cur_arg], "users")) {
5228 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5229 cur_arg += 2;
5230 continue;
5231 } else {
5232 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5233 file, linenum, args[0]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237 }
5238
5239 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5240 } else if (!strcmp(args[0], "user")) { /* new user */
5241 struct auth_users *newuser;
5242 int cur_arg;
5243
5244 if (!*args[1]) {
5245 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5246 file, linenum, args[0]);
5247 err_code |= ERR_ALERT | ERR_FATAL;
5248 goto out;
5249 }
5250
5251 for (newuser = userlist->users; newuser; newuser = newuser->next)
5252 if (!strcmp(newuser->user, args[1])) {
5253 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5254 file, linenum, args[1], userlist->name);
5255 err_code |= ERR_ALERT;
5256 goto out;
5257 }
5258
5259 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5260 if (!newuser) {
5261 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5262 err_code |= ERR_ALERT | ERR_ABORT;
5263 goto out;
5264 }
5265
5266 newuser->user = strdup(args[1]);
5267
5268 newuser->next = userlist->users;
5269 userlist->users = newuser;
5270
5271 cur_arg = 2;
5272
5273 while (*args[cur_arg]) {
5274 if (!strcmp(args[cur_arg], "password")) {
5275#ifndef CONFIG_HAP_CRYPT
5276 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5277 file, linenum);
5278 err_code |= ERR_ALERT;
5279#endif
5280 newuser->pass = strdup(args[cur_arg + 1]);
5281 cur_arg += 2;
5282 continue;
5283 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5284 newuser->pass = strdup(args[cur_arg + 1]);
5285 newuser->flags |= AU_O_INSECURE;
5286 cur_arg += 2;
5287 continue;
5288 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005289 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005290 cur_arg += 2;
5291 continue;
5292 } else {
5293 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5294 file, linenum, args[0]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298 }
5299 } else {
5300 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5301 err_code |= ERR_ALERT | ERR_FATAL;
5302 }
5303
5304out:
5305 return err_code;
5306}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307
5308/*
5309 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005310 * Returns the error code, 0 if OK, or any combination of :
5311 * - ERR_ABORT: must abort ASAP
5312 * - ERR_FATAL: we can continue parsing but not start the service
5313 * - ERR_WARN: a warning has been emitted
5314 * - ERR_ALERT: an alert has been emitted
5315 * Only the two first ones can stop processing, the two others are just
5316 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005318int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005320 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 FILE *f;
5322 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005324 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 if ((f=fopen(file,"r")) == NULL)
5327 return -1;
5328
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005329 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005330 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005331 char *end;
5332 char *args[MAX_LINE_ARGS + 1];
5333 char *line = thisline;
5334
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 linenum++;
5336
5337 end = line + strlen(line);
5338
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005339 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5340 /* Check if we reached the limit and the last char is not \n.
5341 * Watch out for the last line without the terminating '\n'!
5342 */
5343 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005344 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005346 }
5347
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005349 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 line++;
5351
5352 arg = 0;
5353 args[arg] = line;
5354
5355 while (*line && arg < MAX_LINE_ARGS) {
5356 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5357 * C equivalent value. Other combinations left unchanged (eg: \1).
5358 */
5359 if (*line == '\\') {
5360 int skip = 0;
5361 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5362 *line = line[1];
5363 skip = 1;
5364 }
5365 else if (line[1] == 'r') {
5366 *line = '\r';
5367 skip = 1;
5368 }
5369 else if (line[1] == 'n') {
5370 *line = '\n';
5371 skip = 1;
5372 }
5373 else if (line[1] == 't') {
5374 *line = '\t';
5375 skip = 1;
5376 }
5377 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005378 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 unsigned char hex1, hex2;
5380 hex1 = toupper(line[2]) - '0';
5381 hex2 = toupper(line[3]) - '0';
5382 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5383 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5384 *line = (hex1<<4) + hex2;
5385 skip = 3;
5386 }
5387 else {
5388 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005389 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 }
5391 }
5392 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005393 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 end -= skip;
5395 }
5396 line++;
5397 }
5398 else if (*line == '#' || *line == '\n' || *line == '\r') {
5399 /* end of string, end of loop */
5400 *line = 0;
5401 break;
5402 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005403 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005405 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005406 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 line++;
5408 args[++arg] = line;
5409 }
5410 else {
5411 line++;
5412 }
5413 }
5414
5415 /* empty line */
5416 if (!**args)
5417 continue;
5418
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005419 if (*line) {
5420 /* we had to stop due to too many args.
5421 * Let's terminate the string, print the offending part then cut the
5422 * last arg.
5423 */
5424 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5425 line++;
5426 *line = '\0';
5427
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005428 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005429 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005430 err_code |= ERR_ALERT | ERR_FATAL;
5431 args[arg] = line;
5432 }
5433
Willy Tarreau540abe42007-05-02 20:50:16 +02005434 /* zero out remaining args and ensure that at least one entry
5435 * is zeroed out.
5436 */
5437 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 args[arg] = line;
5439 }
5440
Willy Tarreau3842f002009-06-14 11:39:52 +02005441 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005442 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005443 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005444 for (arg=0; *args[arg+1]; arg++)
5445 args[arg] = args[arg+1]; // shift args after inversion
5446 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005447 else if (!strcmp(args[0], "default")) {
5448 kwm = KWM_DEF;
5449 for (arg=0; *args[arg+1]; arg++)
5450 args[arg] = args[arg+1]; // shift args after inversion
5451 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005452
Willy Tarreau3842f002009-06-14 11:39:52 +02005453 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5454 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005455 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005456 }
5457
Willy Tarreau977b8e42006-12-29 14:19:17 +01005458 if (!strcmp(args[0], "listen") ||
5459 !strcmp(args[0], "frontend") ||
5460 !strcmp(args[0], "backend") ||
5461 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005462 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005464 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005465 cursection = strdup(args[0]);
5466 }
5467 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005469 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005470 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005471 }
5472 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005473 confsect = CFG_USERLIST;
5474 free(cursection);
5475 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005476 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005477 else if (!strcmp(args[0], "peers")) {
5478 confsect = CFG_PEERS;
5479 free(cursection);
5480 cursection = strdup(args[0]);
5481 }
5482
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 /* else it's a section keyword */
5484
5485 switch (confsect) {
5486 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005487 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 break;
5489 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005490 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005492 case CFG_USERLIST:
5493 err_code |= cfg_parse_users(file, linenum, args, kwm);
5494 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005495 case CFG_PEERS:
5496 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5497 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005499 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005500 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005502
5503 if (err_code & ERR_ABORT)
5504 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005506 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005507 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005509 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005510}
5511
Willy Tarreaubb925012009-07-23 13:36:36 +02005512/*
5513 * Returns the error code, 0 if OK, or any combination of :
5514 * - ERR_ABORT: must abort ASAP
5515 * - ERR_FATAL: we can continue parsing but not start the service
5516 * - ERR_WARN: a warning has been emitted
5517 * - ERR_ALERT: an alert has been emitted
5518 * Only the two first ones can stop processing, the two others are just
5519 * indicators.
5520 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005521int check_config_validity()
5522{
5523 int cfgerr = 0;
5524 struct proxy *curproxy = NULL;
5525 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005526 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005527 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005528 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529
5530 /*
5531 * Now, check for the integrity of all that we have collected.
5532 */
5533
5534 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005535 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005537 /* first, we will invert the proxy list order */
5538 curproxy = NULL;
5539 while (proxy) {
5540 struct proxy *next;
5541
5542 next = proxy->next;
5543 proxy->next = curproxy;
5544 curproxy = proxy;
5545 if (!next)
5546 break;
5547 proxy = next;
5548 }
5549
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005551 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005552 err_code |= ERR_ALERT | ERR_FATAL;
5553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 }
5555
5556 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005557 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005558 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005559 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005560 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005561 unsigned int next_id;
5562
5563 if (!curproxy->uuid) {
5564 /* proxy ID not set, use automatic numbering with first
5565 * spare entry starting with next_pxid.
5566 */
5567 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5568 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5569 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005570 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005571 next_pxid++;
5572
Willy Tarreau55ea7572007-06-17 19:56:27 +02005573
Willy Tarreaubaaee002006-06-26 02:48:02 +02005574 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005575 /* ensure we don't keep listeners uselessly bound */
5576 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 curproxy = curproxy->next;
5578 continue;
5579 }
5580
Willy Tarreauff01a212009-03-15 13:46:16 +01005581 switch (curproxy->mode) {
5582 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005584 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005585 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5586 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005587 cfgerr++;
5588 }
5589
5590 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005591 Warning("config : servers will be ignored for %s '%s'.\n",
5592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005593 break;
5594
5595 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005596 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005597 break;
5598
5599 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005600 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005601 break;
5602 }
5603
5604 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005605 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5606 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 cfgerr++;
5608 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005609
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005610 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005611 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005612 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005613 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5614 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 cfgerr++;
5616 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005619 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5620 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005621 cfgerr++;
5622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005624 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005625 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5626 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005627 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005628 }
5629 }
5630 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005631 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005632 /* If no LB algo is set in a backend, and we're not in
5633 * transparent mode, dispatch mode nor proxy mode, we
5634 * want to use balance roundrobin by default.
5635 */
5636 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5637 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 }
5639 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005640
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005641 if (curproxy->options2 & PR_O2_DISPATCH) {
5642 curproxy->options &= ~PR_O_TRANSP;
5643 curproxy->options &= ~PR_O_HTTP_PROXY;
5644 }
5645 else if (curproxy->options & PR_O_HTTP_PROXY) {
5646 curproxy->options2 &= ~PR_O2_DISPATCH;
5647 curproxy->options &= ~PR_O_TRANSP;
5648 }
5649 else if (curproxy->options & PR_O_TRANSP) {
5650 curproxy->options2 &= ~PR_O2_DISPATCH;
5651 curproxy->options &= ~PR_O_HTTP_PROXY;
5652 }
5653
Willy Tarreau82936582007-11-30 15:20:09 +01005654 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5655 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005656 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5657 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005658 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005659 }
5660
Willy Tarreauef781042010-01-27 11:53:01 +01005661 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5662 curproxy->options &= ~PR_O2_CHK_SNDST;
5663 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5664 "send-state", proxy_type_str(curproxy), curproxy->id);
5665 err_code |= ERR_WARN;
5666 }
5667
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005668 /* if a default backend was specified, let's find it */
5669 if (curproxy->defbe.name) {
5670 struct proxy *target;
5671
Alex Williams96532db2009-11-01 21:27:13 -05005672 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005673 if (!target) {
5674 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5675 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005676 cfgerr++;
5677 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005678 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5679 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005680 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005681 } else {
5682 free(curproxy->defbe.name);
5683 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005684 /* we force the backend to be present on at least all of
5685 * the frontend's processes.
5686 */
5687 target->bind_proc = curproxy->bind_proc ?
5688 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
5690 }
5691
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005692 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005693 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5694 /* map jump target for ACT_SETBE in req_rep chain */
5695 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005696 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005697 struct proxy *target;
5698
Willy Tarreaua496b602006-12-17 23:15:24 +01005699 if (exp->action != ACT_SETBE)
5700 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005701
Alex Williams96532db2009-11-01 21:27:13 -05005702 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005703 if (!target) {
5704 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5705 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005706 cfgerr++;
5707 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005708 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5709 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005710 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005711 } else {
5712 free((void *)exp->replace);
5713 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005714 /* we force the backend to be present on at least all of
5715 * the frontend's processes.
5716 */
5717 target->bind_proc = curproxy->bind_proc ?
5718 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005719 }
5720 }
5721 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005722
5723 /* find the target proxy for 'use_backend' rules */
5724 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005725 struct proxy *target;
5726
Alex Williams96532db2009-11-01 21:27:13 -05005727 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005728
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005729 if (!target) {
5730 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5731 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005732 cfgerr++;
5733 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005734 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5735 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005736 cfgerr++;
5737 } else {
5738 free((void *)rule->be.name);
5739 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005740 /* we force the backend to be present on at least all of
5741 * the frontend's processes.
5742 */
5743 target->bind_proc = curproxy->bind_proc ?
5744 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005745 }
5746 }
5747
Emeric Brunb982a3d2010-01-04 15:45:53 +01005748 /* find the target table for 'stick' rules */
5749 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5750 struct proxy *target;
5751
Emeric Brun1d33b292010-01-04 15:47:17 +01005752 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5753 if (mrule->flags & STK_IS_STORE)
5754 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5755
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005757 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005758 else
5759 target = curproxy;
5760
5761 if (!target) {
5762 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5763 curproxy->id, mrule->table.name);
5764 cfgerr++;
5765 }
5766 else if (target->table.size == 0) {
5767 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5768 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5769 cfgerr++;
5770 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005771 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005772 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5773 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5774 cfgerr++;
5775 }
5776 else {
5777 free((void *)mrule->table.name);
5778 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005779 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005780 }
5781 }
5782
5783 /* find the target table for 'store response' rules */
5784 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5785 struct proxy *target;
5786
Emeric Brun1d33b292010-01-04 15:47:17 +01005787 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5788
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005790 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005791 else
5792 target = curproxy;
5793
5794 if (!target) {
5795 Alert("Proxy '%s': unable to find store table '%s'.\n",
5796 curproxy->id, mrule->table.name);
5797 cfgerr++;
5798 }
5799 else if (target->table.size == 0) {
5800 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5801 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5802 cfgerr++;
5803 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005804 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005805 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5806 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5807 cfgerr++;
5808 }
5809 else {
5810 free((void *)mrule->table.name);
5811 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005812 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005813 }
5814 }
5815
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005816 /* find the target table for 'tcp-request' layer 4 rules */
5817 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5818 struct proxy *target;
5819
Willy Tarreau56123282010-08-06 19:06:56 +02005820 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005821 continue;
5822
5823 if (trule->act_prm.trk_ctr.table.n)
5824 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5825 else
5826 target = curproxy;
5827
5828 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005829 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5830 curproxy->id, trule->act_prm.trk_ctr.table.n,
5831 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005832 cfgerr++;
5833 }
5834 else if (target->table.size == 0) {
5835 Alert("Proxy '%s': table '%s' used but not configured.\n",
5836 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5837 cfgerr++;
5838 }
5839 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005840 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 +02005841 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5842 cfgerr++;
5843 }
5844 else {
5845 free(trule->act_prm.trk_ctr.table.n);
5846 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005847 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005848 * to pass a list of counters to track and allocate them right here using
5849 * stktable_alloc_data_type().
5850 */
5851 }
5852 }
5853
Willy Tarreaud1f96522010-08-03 19:34:32 +02005854 /* find the target table for 'tcp-request' layer 6 rules */
5855 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5856 struct proxy *target;
5857
Willy Tarreau56123282010-08-06 19:06:56 +02005858 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005859 continue;
5860
5861 if (trule->act_prm.trk_ctr.table.n)
5862 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5863 else
5864 target = curproxy;
5865
5866 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005867 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5868 curproxy->id, trule->act_prm.trk_ctr.table.n,
5869 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005870 cfgerr++;
5871 }
5872 else if (target->table.size == 0) {
5873 Alert("Proxy '%s': table '%s' used but not configured.\n",
5874 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5875 cfgerr++;
5876 }
5877 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005878 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 +02005879 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5880 cfgerr++;
5881 }
5882 else {
5883 free(trule->act_prm.trk_ctr.table.n);
5884 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005885 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005886 * to pass a list of counters to track and allocate them right here using
5887 * stktable_alloc_data_type().
5888 */
5889 }
5890 }
5891
Emeric Brun32da3c42010-09-23 18:39:19 +02005892 if (curproxy->table.peers.name) {
5893 struct peers *curpeers = peers;
5894
5895 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5896 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5897 free((void *)curproxy->table.peers.name);
5898 curproxy->table.peers.p = peers;
5899 break;
5900 }
5901 }
5902
5903 if (!curpeers) {
5904 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5905 curproxy->id, curproxy->table.peers.name);
5906 cfgerr++;
5907 }
5908 else if (!curpeers->peers_fe) {
5909 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5910 curproxy->id, curpeers->id);
5911 cfgerr++;
5912 }
5913 }
5914
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005915 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005916 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005917 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5918 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5919 "proxy", curproxy->id);
5920 cfgerr++;
5921 goto out_uri_auth_compat;
5922 }
5923
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005924 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005925 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005926 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005927 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005928
Willy Tarreau95fa4692010-02-01 13:05:50 +01005929 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5930 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005931
5932 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005933 uri_auth_compat_req[i++] = "realm";
5934 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5935 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005936
Willy Tarreau95fa4692010-02-01 13:05:50 +01005937 uri_auth_compat_req[i++] = "unless";
5938 uri_auth_compat_req[i++] = "{";
5939 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5940 uri_auth_compat_req[i++] = "}";
5941 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005942
Willy Tarreauff011f22011-01-06 17:51:27 +01005943 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5944 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005945 cfgerr++;
5946 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005947 }
5948
Willy Tarreauff011f22011-01-06 17:51:27 +01005949 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005950
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005951 if (curproxy->uri_auth->auth_realm) {
5952 free(curproxy->uri_auth->auth_realm);
5953 curproxy->uri_auth->auth_realm = NULL;
5954 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005955
5956 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005957 }
5958out_uri_auth_compat:
5959
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005960 cfgerr += acl_find_targets(curproxy);
5961
Willy Tarreau2738a142006-07-08 17:28:09 +02005962 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005963 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005964 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005965 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005966 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005967 " | While not properly invalid, you will certainly encounter various problems\n"
5968 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005969 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005970 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005971 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005972 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005973
Willy Tarreau1fa31262007-12-03 00:36:16 +01005974 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5975 * We must still support older configurations, so let's find out whether those
5976 * parameters have been set or must be copied from contimeouts.
5977 */
5978 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005979 if (!curproxy->timeout.tarpit ||
5980 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005981 /* tarpit timeout not set. We search in the following order:
5982 * default.tarpit, curr.connect, default.connect.
5983 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005985 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005987 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005988 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005989 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005990 }
5991 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005992 (!curproxy->timeout.queue ||
5993 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005994 /* queue timeout not set. We search in the following order:
5995 * default.queue, curr.connect, default.connect.
5996 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005997 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005998 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005999 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006000 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006001 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006002 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006003 }
6004 }
6005
Willy Tarreau07a54902010-03-29 18:33:29 +02006006 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006007 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6008 curproxy->check_req = (char *)malloc(curproxy->check_len);
6009 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006010 }
6011
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006012 /* The small pools required for the capture lists */
6013 if (curproxy->nb_req_cap)
6014 curproxy->req_cap_pool = create_pool("ptrcap",
6015 curproxy->nb_req_cap * sizeof(char *),
6016 MEM_F_SHARED);
6017 if (curproxy->nb_rsp_cap)
6018 curproxy->rsp_cap_pool = create_pool("ptrcap",
6019 curproxy->nb_rsp_cap * sizeof(char *),
6020 MEM_F_SHARED);
6021
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006022 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6023 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6024 MEM_F_SHARED);
6025
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 /* first, we will invert the servers list order */
6027 newsrv = NULL;
6028 while (curproxy->srv) {
6029 struct server *next;
6030
6031 next = curproxy->srv->next;
6032 curproxy->srv->next = newsrv;
6033 newsrv = curproxy->srv;
6034 if (!next)
6035 break;
6036 curproxy->srv = next;
6037 }
6038
Willy Tarreaudd701652010-05-25 23:03:02 +02006039 /* assign automatic UIDs to servers which don't have one yet */
6040 next_id = 1;
6041 newsrv = curproxy->srv;
6042 while (newsrv != NULL) {
6043 if (!newsrv->puid) {
6044 /* server ID not set, use automatic numbering with first
6045 * spare entry starting with next_svid.
6046 */
6047 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6048 newsrv->conf.id.key = newsrv->puid = next_id;
6049 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6050 }
6051 next_id++;
6052 newsrv = newsrv->next;
6053 }
6054
Willy Tarreau20697042007-11-15 23:26:18 +01006055 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006056 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006057
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006058 /* We have to initialize the server lookup mechanism depending
6059 * on what LB algorithm was choosen.
6060 */
6061
6062 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6063 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6064 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006065 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6066 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6067 init_server_map(curproxy);
6068 } else {
6069 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6070 fwrr_init_server_groups(curproxy);
6071 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006072 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006073
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006074 case BE_LB_KIND_LC:
6075 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006076 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006077 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006078
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006079 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006080 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6081 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6082 chash_init_server_tree(curproxy);
6083 } else {
6084 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6085 init_server_map(curproxy);
6086 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006087 break;
6088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089
6090 if (curproxy->options & PR_O_LOGASAP)
6091 curproxy->to_log &= ~LW_BYTES;
6092
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006093 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6094 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6095 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6096 proxy_type_str(curproxy), curproxy->id);
6097 err_code |= ERR_WARN;
6098 }
6099
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006100 if (curproxy->mode != PR_MODE_HTTP) {
6101 int optnum;
6102
6103 if (curproxy->options & PR_O_COOK_ANY) {
6104 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6105 proxy_type_str(curproxy), curproxy->id);
6106 err_code |= ERR_WARN;
6107 }
6108
6109 if (curproxy->uri_auth) {
6110 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6111 proxy_type_str(curproxy), curproxy->id);
6112 err_code |= ERR_WARN;
6113 curproxy->uri_auth = NULL;
6114 }
6115
6116 if (curproxy->options & PR_O_FWDFOR) {
6117 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6118 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6119 err_code |= ERR_WARN;
6120 curproxy->options &= ~PR_O_FWDFOR;
6121 }
6122
6123 if (curproxy->options & PR_O_ORGTO) {
6124 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6125 "originalto", proxy_type_str(curproxy), curproxy->id);
6126 err_code |= ERR_WARN;
6127 curproxy->options &= ~PR_O_ORGTO;
6128 }
6129
6130 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6131 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6132 (curproxy->cap & cfg_opts[optnum].cap) &&
6133 (curproxy->options & cfg_opts[optnum].val)) {
6134 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6135 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6136 err_code |= ERR_WARN;
6137 curproxy->options &= ~cfg_opts[optnum].val;
6138 }
6139 }
6140
6141 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6142 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6143 (curproxy->cap & cfg_opts2[optnum].cap) &&
6144 (curproxy->options2 & cfg_opts2[optnum].val)) {
6145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6146 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6147 err_code |= ERR_WARN;
6148 curproxy->options2 &= ~cfg_opts2[optnum].val;
6149 }
6150 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006151
Willy Tarreauefa5f512010-03-30 20:13:29 +02006152#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006153 if (curproxy->bind_hdr_occ) {
6154 curproxy->bind_hdr_occ = 0;
6155 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6156 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6157 err_code |= ERR_WARN;
6158 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006160 }
6161
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006163 * ensure that we're not cross-dressing a TCP server into HTTP.
6164 */
6165 newsrv = curproxy->srv;
6166 while (newsrv != NULL) {
6167 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6169 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006170 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006171 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006172
Willy Tarreauefa5f512010-03-30 20:13:29 +02006173#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006174 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6175 newsrv->bind_hdr_occ = 0;
6176 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6177 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6178 err_code |= ERR_WARN;
6179 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006180#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006181 newsrv = newsrv->next;
6182 }
6183
6184 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006185 * If this server supports a maxconn parameter, it needs a dedicated
6186 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006187 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 */
6189 newsrv = curproxy->srv;
6190 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006191 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 /* Only 'minconn' was specified, or it was higher than or equal
6193 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6194 * this will avoid further useless expensive computations.
6195 */
6196 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006197 } else if (newsrv->maxconn && !newsrv->minconn) {
6198 /* minconn was not specified, so we set it to maxconn */
6199 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200 }
6201
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006202 if (newsrv->trackit) {
6203 struct proxy *px;
6204 struct server *srv;
6205 char *pname, *sname;
6206
6207 pname = newsrv->trackit;
6208 sname = strrchr(pname, '/');
6209
6210 if (sname)
6211 *sname++ = '\0';
6212 else {
6213 sname = pname;
6214 pname = NULL;
6215 }
6216
6217 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006218 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006219 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006220 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6221 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006222 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006223 cfgerr++;
6224 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006225 }
6226 } else
6227 px = curproxy;
6228
6229 srv = findserver(px, sname);
6230 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006231 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6232 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006233 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006234 cfgerr++;
6235 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006236 }
6237
6238 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006239 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006240 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006241 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006242 newsrv->id, px->id, srv->id);
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 (curproxy != px &&
6248 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006249 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006250 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006251 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006252 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006253 cfgerr++;
6254 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006255 }
6256
6257 newsrv->tracked = srv;
6258 newsrv->tracknext = srv->tracknext;
6259 srv->tracknext = newsrv;
6260
6261 free(newsrv->trackit);
6262 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006263 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 newsrv = newsrv->next;
6265 }
6266
Willy Tarreauc1a21672009-08-16 22:37:44 +02006267 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006268 curproxy->accept = frontend_accept;
6269
Willy Tarreauc1a21672009-08-16 22:37:44 +02006270 if (curproxy->tcp_req.inspect_delay ||
6271 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006272 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006273
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006274 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006275 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006276 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006277 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006278
6279 /* both TCP and HTTP must check switching rules */
6280 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6281 }
6282
6283 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006284 if (curproxy->tcp_req.inspect_delay ||
6285 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6286 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6287
Emeric Brun97679e72010-09-23 17:56:44 +02006288 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6289 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6290
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006291 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006292 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006293 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006294 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006295
6296 /* If the backend does requires RDP cookie persistence, we have to
6297 * enable the corresponding analyser.
6298 */
6299 if (curproxy->options2 & PR_O2_RDPC_PRST)
6300 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6301 }
6302
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006303 listener = NULL;
6304 while (curproxy->listen) {
6305 struct listener *next;
6306
6307 next = curproxy->listen->next;
6308 curproxy->listen->next = listener;
6309 listener = curproxy->listen;
6310
6311 if (!next)
6312 break;
6313
6314 curproxy->listen = next;
6315 }
6316
Willy Tarreaue6b98942007-10-29 01:09:36 +01006317 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006318 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006319 listener = curproxy->listen;
6320 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006321 if (!listener->luid) {
6322 /* listener ID not set, use automatic numbering with first
6323 * spare entry starting with next_luid.
6324 */
6325 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6326 listener->conf.id.key = listener->luid = next_id;
6327 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006328 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006329 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006330
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006331 /* enable separate counters */
6332 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6333 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6334 if (!listener->name) {
6335 sprintf(trash, "sock-%d", listener->luid);
6336 listener->name = strdup(trash);
6337 }
6338 }
6339
Willy Tarreaue6b98942007-10-29 01:09:36 +01006340 if (curproxy->options & PR_O_TCP_NOLING)
6341 listener->options |= LI_O_NOLINGER;
6342 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006343 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006344 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006345 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006346 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006347 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006348 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006349
Willy Tarreau8a956912010-10-15 14:27:08 +02006350 if (listener->options & LI_O_ACC_PROXY)
6351 listener->analysers |= AN_REQ_DECODE_PROXY;
6352
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006353 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6354 listener->options |= LI_O_TCP_RULES;
6355
Willy Tarreaude3041d2010-05-31 10:56:17 +02006356 if (curproxy->mon_mask.s_addr)
6357 listener->options |= LI_O_CHK_MONNET;
6358
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006359 /* smart accept mode is automatic in HTTP mode */
6360 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6361 (curproxy->mode == PR_MODE_HTTP &&
6362 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6363 listener->options |= LI_O_NOQUICKACK;
6364
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006365 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006366 listener = listener->next;
6367 }
6368
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006369 /* Check multi-process mode compatibility for the current proxy */
6370 if (global.nbproc > 1) {
6371 int nbproc = 0;
6372 if (curproxy->bind_proc) {
6373 int proc;
6374 for (proc = 0; proc < global.nbproc; proc++) {
6375 if (curproxy->bind_proc & (1 << proc)) {
6376 nbproc++;
6377 }
6378 }
6379 } else {
6380 nbproc = global.nbproc;
6381 }
6382 if (curproxy->table.peers.name) {
6383 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6384 curproxy->id);
6385 cfgerr++;
6386 }
6387 if (nbproc > 1) {
6388 if (curproxy->uri_auth) {
6389 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6390 curproxy->id);
6391 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6392 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6393 curproxy->id);
6394 }
6395 }
6396 if (curproxy->appsession_name) {
6397 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6398 curproxy->id);
6399 }
6400 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6401 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6402 curproxy->id);
6403 }
6404 }
6405 }
6406
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 curproxy = curproxy->next;
6408 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006409
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006410 /* Check multi-process mode compatibility */
6411 if (global.nbproc > 1) {
6412 if (global.stats_fe) {
6413 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6414 }
6415 }
6416
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006417 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6418 struct auth_users *curuser;
6419 int g;
6420
6421 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6422 unsigned int group_mask = 0;
6423 char *group = NULL;
6424
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006425 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006426 continue;
6427
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006428 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006429
6430 for (g = 0; g < curuserlist->grpcnt; g++)
6431 if (!strcmp(curuserlist->groups[g], group))
6432 break;
6433
6434 if (g == curuserlist->grpcnt) {
6435 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6436 curuserlist->name, group, curuser->user);
6437 err_code |= ERR_ALERT | ERR_FATAL;
6438 goto out;
6439 }
6440
6441 group_mask |= (1 << g);
6442 }
6443
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006444 free(curuser->u.groups);
6445 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006446 }
6447
6448 for (g = 0; g < curuserlist->grpcnt; g++) {
6449 char *user = NULL;
6450
6451 if (!curuserlist->groupusers[g])
6452 continue;
6453
6454 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6455 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6456 if (!strcmp(curuser->user, user))
6457 break;
6458
6459 if (!curuser) {
6460 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6461 curuserlist->name, user, curuserlist->groups[g]);
6462 err_code |= ERR_ALERT | ERR_FATAL;
6463 goto out;
6464 }
6465
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006466 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006467 }
6468
6469 free(curuserlist->groupusers[g]);
6470 }
6471
6472 free(curuserlist->groupusers);
6473
6474#ifdef DEBUG_AUTH
6475 for (g = 0; g < curuserlist->grpcnt; g++) {
6476 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6477
6478 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6479 if (curuser->group_mask & (1 << g))
6480 fprintf(stderr, " %s", curuser->user);
6481 }
6482
6483 fprintf(stderr, "\n");
6484 }
6485#endif
6486
Willy Tarreaufbb78422011-06-05 15:38:35 +02006487 }
6488
6489 /* automatically compute fullconn if not set. We must not do it in the
6490 * loop above because cross-references are not yet fully resolved.
6491 */
6492 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6493 /* If <fullconn> is not set, let's set it to 10% of the sum of
6494 * the possible incoming frontend's maxconns.
6495 */
6496 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6497 struct proxy *fe;
6498 int total = 0;
6499
6500 /* sum up the number of maxconns of frontends which
6501 * reference this backend at least once or which are
6502 * the same one ('listen').
6503 */
6504 for (fe = proxy; fe; fe = fe->next) {
6505 struct switching_rule *rule;
6506 struct hdr_exp *exp;
6507 int found = 0;
6508
6509 if (!(fe->cap & PR_CAP_FE))
6510 continue;
6511
6512 if (fe == curproxy) /* we're on a "listen" instance */
6513 found = 1;
6514
6515 if (fe->defbe.be == curproxy) /* "default_backend" */
6516 found = 1;
6517
6518 /* check if a "use_backend" rule matches */
6519 if (!found) {
6520 list_for_each_entry(rule, &fe->switching_rules, list) {
6521 if (rule->be.backend == curproxy) {
6522 found = 1;
6523 break;
6524 }
6525 }
6526 }
6527
6528 /* check if a "reqsetbe" rule matches */
6529 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6530 if (exp->action == ACT_SETBE &&
6531 (struct proxy *)exp->replace == curproxy) {
6532 found = 1;
6533 break;
6534 }
6535 }
6536
6537 /* now we've checked all possible ways to reference a backend
6538 * from a frontend.
6539 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006540 if (!found)
6541 continue;
6542 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006543 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006544 /* we have the sum of the maxconns in <total>. We only
6545 * keep 10% of that sum to set the default fullconn, with
6546 * a hard minimum of 1 (to avoid a divide by zero).
6547 */
6548 curproxy->fullconn = (total + 9) / 10;
6549 if (!curproxy->fullconn)
6550 curproxy->fullconn = 1;
6551 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006552 }
6553
Willy Tarreau056f5682010-06-06 15:51:11 +02006554 /* initialize stick-tables on backend capable proxies. This must not
6555 * be done earlier because the data size may be discovered while parsing
6556 * other proxies.
6557 */
6558 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006559 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006560
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006561 /*
6562 * Recount currently required checks.
6563 */
6564
6565 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6566 int optnum;
6567
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006568 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6569 if (curproxy->options & cfg_opts[optnum].val)
6570 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006571
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006572 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6573 if (curproxy->options2 & cfg_opts2[optnum].val)
6574 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006575 }
6576
Willy Tarreaubb925012009-07-23 13:36:36 +02006577 if (cfgerr > 0)
6578 err_code |= ERR_ALERT | ERR_FATAL;
6579 out:
6580 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581}
6582
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006583/*
6584 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6585 * parsing sessions.
6586 */
6587void cfg_register_keywords(struct cfg_kw_list *kwl)
6588{
6589 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6590}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006592/*
6593 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6594 */
6595void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6596{
6597 LIST_DEL(&kwl->list);
6598 LIST_INIT(&kwl->list);
6599}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600
6601/*
6602 * Local variables:
6603 * c-indent-level: 8
6604 * c-basic-offset: 8
6605 * End:
6606 */