blob: 40c46d50c8eedd7b833bef4a5a35bb4e9ba25fbe [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;
3479 curproxy->check_req[8] = 1;
3480 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3481 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3482 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3483 cur_arg += 2;
3484 } else {
3485 /* unknown suboption - catchall */
3486 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3487 file, linenum, args[0], args[1]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 } /* end while loop */
3492 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003493 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003494 else if (!strcmp(args[1], "ldap-check")) {
3495 /* use LDAP request to check servers' health */
3496 free(curproxy->check_req);
3497 curproxy->check_req = NULL;
3498 curproxy->options &= ~PR_O_HTTP_CHK;
3499 curproxy->options &= ~PR_O_SMTP_CHK;
3500 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3501 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003502 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003503 curproxy->options2 |= PR_O2_LDAP_CHK;
3504
3505 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3506 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3507 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3508 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003509 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003510 int cur_arg;
3511
3512 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3513 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003514 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003515
3516 curproxy->options |= PR_O_FWDFOR;
3517
3518 free(curproxy->fwdfor_hdr_name);
3519 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3520 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3521
3522 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3523 cur_arg = 2;
3524 while (*(args[cur_arg])) {
3525 if (!strcmp(args[cur_arg], "except")) {
3526 /* suboption except - needs additional argument for it */
3527 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3528 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3529 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003532 }
3533 /* flush useless bits */
3534 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003535 cur_arg += 2;
3536 } else if (!strcmp(args[cur_arg], "header")) {
3537 /* suboption header - needs additional argument for it */
3538 if (*(args[cur_arg+1]) == 0) {
3539 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3540 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 }
3544 free(curproxy->fwdfor_hdr_name);
3545 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3546 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3547 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003548 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003549 /* unknown suboption - catchall */
3550 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3551 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003554 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003555 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003556 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003557 else if (!strcmp(args[1], "originalto")) {
3558 int cur_arg;
3559
3560 /* insert x-original-to field, but not for the IP address listed as an except.
3561 * set default options (ie: bitfield, header name, etc)
3562 */
3563
3564 curproxy->options |= PR_O_ORGTO;
3565
3566 free(curproxy->orgto_hdr_name);
3567 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3568 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3569
3570 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3571 cur_arg = 2;
3572 while (*(args[cur_arg])) {
3573 if (!strcmp(args[cur_arg], "except")) {
3574 /* suboption except - needs additional argument for it */
3575 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3576 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3577 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003580 }
3581 /* flush useless bits */
3582 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3583 cur_arg += 2;
3584 } else if (!strcmp(args[cur_arg], "header")) {
3585 /* suboption header - needs additional argument for it */
3586 if (*(args[cur_arg+1]) == 0) {
3587 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3588 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003591 }
3592 free(curproxy->orgto_hdr_name);
3593 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3594 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3595 cur_arg += 2;
3596 } else {
3597 /* unknown suboption - catchall */
3598 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3599 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003600 err_code |= ERR_ALERT | ERR_FATAL;
3601 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003602 }
3603 } /* end while loop */
3604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 else {
3606 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
Willy Tarreau93893792009-07-23 13:19:11 +02003610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003612 else if (!strcmp(args[0], "default_backend")) {
3613 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003615
3616 if (*(args[1]) == 0) {
3617 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003620 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003621 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003622 curproxy->defbe.name = strdup(args[1]);
3623 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003626 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003628 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3629 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003630 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 /* enable reconnections to dispatch */
3632 curproxy->options |= PR_O_REDISP;
3633 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003634 else if (!strcmp(args[0], "http-check")) {
3635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003636 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003637
3638 if (strcmp(args[1], "disable-on-404") == 0) {
3639 /* enable a graceful server shutdown on an HTTP 404 response */
3640 curproxy->options |= PR_O_DISABLE404;
3641 }
Willy Tarreauef781042010-01-27 11:53:01 +01003642 else if (strcmp(args[1], "send-state") == 0) {
3643 /* enable emission of the apparent state of a server in HTTP checks */
3644 curproxy->options2 |= PR_O2_CHK_SNDST;
3645 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003646 else if (strcmp(args[1], "expect") == 0) {
3647 const char *ptr_arg;
3648 int cur_arg;
3649
3650 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3651 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
3654 }
3655
3656 cur_arg = 2;
3657 /* consider exclamation marks, sole or at the beginning of a word */
3658 while (*(ptr_arg = args[cur_arg])) {
3659 while (*ptr_arg == '!') {
3660 curproxy->options2 ^= PR_O2_EXP_INV;
3661 ptr_arg++;
3662 }
3663 if (*ptr_arg)
3664 break;
3665 cur_arg++;
3666 }
3667 /* now ptr_arg points to the beginning of a word past any possible
3668 * exclamation mark, and cur_arg is the argument which holds this word.
3669 */
3670 if (strcmp(ptr_arg, "status") == 0) {
3671 if (!*(args[cur_arg + 1])) {
3672 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3673 file, linenum, args[0], args[1], ptr_arg);
3674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
3676 }
3677 curproxy->options2 |= PR_O2_EXP_STS;
3678 curproxy->expect_str = strdup(args[cur_arg + 1]);
3679 }
3680 else if (strcmp(ptr_arg, "string") == 0) {
3681 if (!*(args[cur_arg + 1])) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3683 file, linenum, args[0], args[1], ptr_arg);
3684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
3686 }
3687 curproxy->options2 |= PR_O2_EXP_STR;
3688 curproxy->expect_str = strdup(args[cur_arg + 1]);
3689 }
3690 else if (strcmp(ptr_arg, "rstatus") == 0) {
3691 if (!*(args[cur_arg + 1])) {
3692 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3693 file, linenum, args[0], args[1], ptr_arg);
3694 err_code |= ERR_ALERT | ERR_FATAL;
3695 goto out;
3696 }
3697 curproxy->options2 |= PR_O2_EXP_RSTS;
3698 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3699 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3700 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3701 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
3704 }
3705 }
3706 else if (strcmp(ptr_arg, "rstring") == 0) {
3707 if (!*(args[cur_arg + 1])) {
3708 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3709 file, linenum, args[0], args[1], ptr_arg);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
3713 curproxy->options2 |= PR_O2_EXP_RSTR;
3714 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3715 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3716 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3717 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 }
3722 else {
3723 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3724 file, linenum, args[0], args[1], ptr_arg);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003729 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003730 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003733 }
3734 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003735 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003736 if (curproxy == &defproxy) {
3737 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003740 }
3741
Willy Tarreaub80c2302007-11-30 20:51:32 +01003742 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003744
3745 if (strcmp(args[1], "fail") == 0) {
3746 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003747 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003748 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3749 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003752 }
3753
Willy Tarreauef6494c2010-01-28 17:12:36 +01003754 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003755 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3756 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003757 err_code |= ERR_ALERT | ERR_FATAL;
3758 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003759 }
3760 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3761 }
3762 else {
3763 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003766 }
3767 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768#ifdef TPROXY
3769 else if (!strcmp(args[0], "transparent")) {
3770 /* enable transparent proxy connections */
3771 curproxy->options |= PR_O_TRANSP;
3772 }
3773#endif
3774 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003775 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003777
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 if (*(args[1]) == 0) {
3779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
3783 curproxy->maxconn = atol(args[1]);
3784 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003785 else if (!strcmp(args[0], "backlog")) { /* backlog */
3786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003788
3789 if (*(args[1]) == 0) {
3790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003793 }
3794 curproxy->backlog = atol(args[1]);
3795 }
Willy Tarreau86034312006-12-29 00:10:33 +01003796 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003797 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003799
Willy Tarreau86034312006-12-29 00:10:33 +01003800 if (*(args[1]) == 0) {
3801 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003804 }
3805 curproxy->fullconn = atol(args[1]);
3806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3808 if (*(args[1]) == 0) {
3809 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003813 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3814 if (err) {
3815 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3816 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003819 }
3820 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 }
3822 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003823 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 if (curproxy == &defproxy) {
3825 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003829 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003831
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 if (strchr(args[1], ':') == NULL) {
3833 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003837 sk = str2sa(args[1]);
3838 if (!sk) {
3839 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003844 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003845 }
3846 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003847 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003849
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003850 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003851 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3852 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003857 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3859 err_code |= ERR_WARN;
3860
3861 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3862 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3863 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3864 }
3865 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3866 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3867 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3868 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003869 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3870 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3871 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3872 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003873 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003874 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003879 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003881 char *rport, *raddr;
3882 short realport = 0;
3883 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003885 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003890 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892
3893 if (!*args[2]) {
3894 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3895 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003899
3900 err = invalid_char(args[1]);
3901 if (err) {
3902 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3903 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003906 }
3907
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003908 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003909 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003910
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003911 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3912 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3913 err_code |= ERR_ALERT | ERR_ABORT;
3914 goto out;
3915 }
3916
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003917 /* the servers are linked backwards first */
3918 newsrv->next = curproxy->srv;
3919 curproxy->srv = newsrv;
3920 newsrv->proxy = curproxy;
3921 newsrv->conf.file = file;
3922 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003924 LIST_INIT(&newsrv->pendconns);
3925 do_check = 0;
3926 newsrv->state = SRV_RUNNING; /* early server setup */
3927 newsrv->last_change = now.tv_sec;
3928 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003929
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003930 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003931 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003932 * - IP: => port=+0, relative
3933 * - IP:N => port=N, absolute
3934 * - IP:+N => port=+N, relative
3935 * - IP:-N => port=-N, relative
3936 */
3937 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003938 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003939 if (rport) {
3940 *rport++ = 0;
3941 realport = atol(rport);
3942 if (!isdigit((unsigned char)*rport))
3943 newsrv->state |= SRV_MAPPORTS;
3944 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003946
Willy Tarreaufab5a432011-03-04 15:31:53 +01003947 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003949 if (!sk) {
3950 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
3953 }
3954 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003955
3956 switch (newsrv->addr.ss_family) {
3957 case AF_INET:
3958 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3959 break;
3960 case AF_INET6:
3961 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3962 break;
3963 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003964
3965 newsrv->check_port = curproxy->defsrv.check_port;
3966 newsrv->inter = curproxy->defsrv.inter;
3967 newsrv->fastinter = curproxy->defsrv.fastinter;
3968 newsrv->downinter = curproxy->defsrv.downinter;
3969 newsrv->rise = curproxy->defsrv.rise;
3970 newsrv->fall = curproxy->defsrv.fall;
3971 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3972 newsrv->minconn = curproxy->defsrv.minconn;
3973 newsrv->maxconn = curproxy->defsrv.maxconn;
3974 newsrv->slowstart = curproxy->defsrv.slowstart;
3975 newsrv->onerror = curproxy->defsrv.onerror;
3976 newsrv->consecutive_errors_limit
3977 = curproxy->defsrv.consecutive_errors_limit;
3978 newsrv->uweight = newsrv->iweight
3979 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003981 newsrv->curfd = -1; /* no health-check in progress */
3982 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 cur_arg = 3;
3985 } else {
3986 newsrv = &curproxy->defsrv;
3987 cur_arg = 1;
3988 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003989
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003991 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003992 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003993
3994 if (!*args[cur_arg + 1]) {
3995 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3996 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999 }
4000
4001 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004002 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004003
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004004 if (newsrv->puid <= 0) {
4005 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004006 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004009 }
4010
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004011 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4012 if (node) {
4013 struct server *target = container_of(node, struct server, conf.id);
4014 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4015 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004020 cur_arg += 2;
4021 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023 newsrv->cookie = strdup(args[cur_arg + 1]);
4024 newsrv->cklen = strlen(args[cur_arg + 1]);
4025 cur_arg += 2;
4026 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004028 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4029 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4030 cur_arg += 2;
4031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004033 if (!*args[cur_arg + 1]) {
4034 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4035 file, linenum, args[cur_arg]);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004041 if (newsrv->rise <= 0) {
4042 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4043 file, linenum, args[cur_arg]);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047
Willy Tarreau96839092010-03-29 10:02:24 +02004048 if (newsrv->health)
4049 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004050 cur_arg += 2;
4051 }
4052 else if (!strcmp(args[cur_arg], "fall")) {
4053 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004054
4055 if (!*args[cur_arg + 1]) {
4056 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4057 file, linenum, args[cur_arg]);
4058 err_code |= ERR_ALERT | ERR_FATAL;
4059 goto out;
4060 }
4061
4062 if (newsrv->fall <= 0) {
4063 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4064 file, linenum, args[cur_arg]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 cur_arg += 2;
4070 }
4071 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004072 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4073 if (err) {
4074 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4075 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004076 err_code |= ERR_ALERT | ERR_FATAL;
4077 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004078 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004079 if (val <= 0) {
4080 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4081 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004084 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004085 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 cur_arg += 2;
4087 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004088 else if (!strcmp(args[cur_arg], "fastinter")) {
4089 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4090 if (err) {
4091 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4092 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004095 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004096 if (val <= 0) {
4097 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4098 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004101 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 newsrv->fastinter = val;
4103 cur_arg += 2;
4104 }
4105 else if (!strcmp(args[cur_arg], "downinter")) {
4106 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4107 if (err) {
4108 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4109 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004112 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004113 if (val <= 0) {
4114 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4115 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004118 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004119 newsrv->downinter = val;
4120 cur_arg += 2;
4121 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004122 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004123 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004124 if (!sk) {
4125 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004130 cur_arg += 2;
4131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 else if (!strcmp(args[cur_arg], "port")) {
4133 newsrv->check_port = atol(args[cur_arg + 1]);
4134 cur_arg += 2;
4135 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 newsrv->state |= SRV_BACKUP;
4138 cur_arg ++;
4139 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4141 newsrv->state |= SRV_SEND_PROXY;
4142 cur_arg ++;
4143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004144 else if (!strcmp(args[cur_arg], "weight")) {
4145 int w;
4146 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004147 if (w < 0 || w > 256) {
4148 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004149 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004150 err_code |= ERR_ALERT | ERR_FATAL;
4151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004153 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 cur_arg += 2;
4155 }
4156 else if (!strcmp(args[cur_arg], "minconn")) {
4157 newsrv->minconn = atol(args[cur_arg + 1]);
4158 cur_arg += 2;
4159 }
4160 else if (!strcmp(args[cur_arg], "maxconn")) {
4161 newsrv->maxconn = atol(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004164 else if (!strcmp(args[cur_arg], "maxqueue")) {
4165 newsrv->maxqueue = atol(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004168 else if (!strcmp(args[cur_arg], "slowstart")) {
4169 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004170 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004171 if (err) {
4172 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4173 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004176 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004177 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004178 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4179 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004182 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004183 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004184 cur_arg += 2;
4185 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004187
4188 if (!*args[cur_arg + 1]) {
4189 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4190 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004193 }
4194
4195 newsrv->trackit = strdup(args[cur_arg + 1]);
4196
4197 cur_arg += 2;
4198 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004199 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004200 global.maxsock++;
4201 do_check = 1;
4202 cur_arg += 1;
4203 }
Willy Tarreau96839092010-03-29 10:02:24 +02004204 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4205 newsrv->state |= SRV_MAINTAIN;
4206 newsrv->state &= ~SRV_RUNNING;
4207 newsrv->health = 0;
4208 cur_arg += 1;
4209 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004210 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004211 if (!strcmp(args[cur_arg + 1], "none"))
4212 newsrv->observe = HANA_OBS_NONE;
4213 else if (!strcmp(args[cur_arg + 1], "layer4"))
4214 newsrv->observe = HANA_OBS_LAYER4;
4215 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4216 if (curproxy->mode != PR_MODE_HTTP) {
4217 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4218 file, linenum, args[cur_arg + 1]);
4219 err_code |= ERR_ALERT;
4220 }
4221 newsrv->observe = HANA_OBS_LAYER7;
4222 }
4223 else {
4224 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004225 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004226 file, linenum, args[cur_arg], args[cur_arg + 1]);
4227 err_code |= ERR_ALERT | ERR_FATAL;
4228 goto out;
4229 }
4230
4231 cur_arg += 2;
4232 }
4233 else if (!strcmp(args[cur_arg], "on-error")) {
4234 if (!strcmp(args[cur_arg + 1], "fastinter"))
4235 newsrv->onerror = HANA_ONERR_FASTINTER;
4236 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4237 newsrv->onerror = HANA_ONERR_FAILCHK;
4238 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4239 newsrv->onerror = HANA_ONERR_SUDDTH;
4240 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4241 newsrv->onerror = HANA_ONERR_MARKDWN;
4242 else {
4243 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004244 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004245 file, linenum, args[cur_arg], args[cur_arg + 1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249
4250 cur_arg += 2;
4251 }
4252 else if (!strcmp(args[cur_arg], "error-limit")) {
4253 if (!*args[cur_arg + 1]) {
4254 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4255 file, linenum, args[cur_arg]);
4256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
4258 }
4259
4260 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4261
4262 if (newsrv->consecutive_errors_limit <= 0) {
4263 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4264 file, linenum, args[cur_arg]);
4265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
4267 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004268 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004269 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004270 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004271 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004272 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004273
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004275#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004276 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004277 file, linenum, "source", "usesrc");
4278#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004279 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004281#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004284 }
4285 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004286 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4287 if (!sk) {
4288 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4289 err_code |= ERR_ALERT | ERR_FATAL;
4290 goto out;
4291 }
4292 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004293
4294 if (port_low != port_high) {
4295 int i;
4296 if (port_low <= 0 || port_low > 65535 ||
4297 port_high <= 0 || port_high > 65535 ||
4298 port_low > port_high) {
4299 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4300 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004303 }
4304 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4305 for (i = 0; i < newsrv->sport_range->size; i++)
4306 newsrv->sport_range->ports[i] = port_low + i;
4307 }
4308
Willy Tarreaubaaee002006-06-26 02:48:02 +02004309 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004310 while (*(args[cur_arg])) {
4311 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004312#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4313#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004314 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4315 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4316 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_FATAL;
4318 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004319 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004320#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004321 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004322 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004323 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004324 err_code |= ERR_ALERT | ERR_FATAL;
4325 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004326 }
4327 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004328 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004329 newsrv->state |= SRV_TPROXY_CLI;
4330 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004331 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004332 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004333 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4334 char *name, *end;
4335
4336 name = args[cur_arg+1] + 7;
4337 while (isspace(*name))
4338 name++;
4339
4340 end = name;
4341 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4342 end++;
4343
4344 newsrv->state &= ~SRV_TPROXY_MASK;
4345 newsrv->state |= SRV_TPROXY_DYN;
4346 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4347 newsrv->bind_hdr_len = end - name;
4348 memcpy(newsrv->bind_hdr_name, name, end - name);
4349 newsrv->bind_hdr_name[end-name] = '\0';
4350 newsrv->bind_hdr_occ = -1;
4351
4352 /* now look for an occurrence number */
4353 while (isspace(*end))
4354 end++;
4355 if (*end == ',') {
4356 end++;
4357 name = end;
4358 if (*end == '-')
4359 end++;
4360 while (isdigit(*end))
4361 end++;
4362 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4363 }
4364
4365 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4366 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4367 " occurrences values smaller than %d.\n",
4368 file, linenum, MAX_HDR_HISTORY);
4369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004373 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004374 if (!sk) {
4375 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
4378 }
4379 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 }
4382 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004383#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004384 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004385#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 cur_arg += 2;
4387 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004388#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004390 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004393#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4394 } /* "usesrc" */
4395
4396 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4397#ifdef SO_BINDTODEVICE
4398 if (!*args[cur_arg + 1]) {
4399 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403 }
4404 if (newsrv->iface_name)
4405 free(newsrv->iface_name);
4406
4407 newsrv->iface_name = strdup(args[cur_arg + 1]);
4408 newsrv->iface_len = strlen(newsrv->iface_name);
4409 global.last_checks |= LSTCHK_NETADM;
4410#else
4411 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4412 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004415#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416 cur_arg += 2;
4417 continue;
4418 }
4419 /* this keyword in not an option of "source" */
4420 break;
4421 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004423 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004424 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4425 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004429 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004430 if (!defsrv)
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004431 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', '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 +01004432 file, linenum, newsrv->id);
4433 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004434 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 +01004435 file, linenum);
4436
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 }
4440 }
4441
4442 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004443 if (newsrv->trackit) {
4444 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4445 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004448 }
4449
David du Colombier6f5ccb12011-03-10 22:26:24 +01004450 switch (newsrv->check_addr.ss_family) {
4451 case AF_INET:
4452 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4453 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4454 break;
4455 case AF_INET6:
4456 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4457 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4458 break;
4459 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004460
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4462 newsrv->check_port = realport; /* by default */
4463 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004464 /* not yet valid, because no port was set on
4465 * the server either. We'll check if we have
4466 * a known port on the first listener.
4467 */
4468 struct listener *l;
4469 l = curproxy->listen;
4470 if (l) {
4471 int port;
4472 port = (l->addr.ss_family == AF_INET6)
4473 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4474 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4475 newsrv->check_port = port;
4476 }
4477 }
4478 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4480 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004484
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004485 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004486 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004487 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4488 err_code |= ERR_ALERT | ERR_ABORT;
4489 goto out;
4490 }
4491
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004492 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 newsrv->state |= SRV_CHECKED;
4494 }
4495
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004496 if (!defsrv) {
4497 if (newsrv->state & SRV_BACKUP)
4498 curproxy->srv_bck++;
4499 else
4500 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004501
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004502 newsrv->prev_state = newsrv->state;
4503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
4505 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004506 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 int facility;
4508
4509 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4510 curproxy->logfac1 = global.logfac1;
4511 curproxy->logsrv1 = global.logsrv1;
4512 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004513 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 curproxy->logfac2 = global.logfac2;
4515 curproxy->logsrv2 = global.logsrv2;
4516 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004517 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
4519 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004520 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521
4522 facility = get_log_facility(args[2]);
4523 if (facility < 0) {
4524 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4525 exit(1);
4526 }
4527
4528 level = 7; /* max syslog level = debug */
4529 if (*(args[3])) {
4530 level = get_log_level(args[3]);
4531 if (level < 0) {
4532 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4533 exit(1);
4534 }
4535 }
4536
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004537 minlvl = 0; /* limit syslog level to this level (emerg) */
4538 if (*(args[4])) {
4539 minlvl = get_log_level(args[4]);
4540 if (level < 0) {
4541 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4542 exit(1);
4543 }
4544 }
4545
Robert Tsai81ae1952007-12-05 10:47:29 +01004546 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004547 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004548 if (!sk) {
4549 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004550 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004554 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004555 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004556 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004557 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004558 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004562 logsrv.addr = *sk;
4563 if (!get_host_port(&logsrv.addr))
4564 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566
4567 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004568 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 curproxy->logfac1 = facility;
4570 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004571 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572 }
4573 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004574 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 curproxy->logfac2 = facility;
4576 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004577 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
4579 else {
4580 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
4584 }
4585 else {
4586 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4587 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 }
4591 }
4592 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004593 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004594 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004595
Willy Tarreau977b8e42006-12-29 14:19:17 +01004596 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004598
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004600 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4601 file, linenum, "source", "usesrc", "interface");
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 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004605
4606 /* we must first clear any optional default setting */
4607 curproxy->options &= ~PR_O_TPXY_MASK;
4608 free(curproxy->iface_name);
4609 curproxy->iface_name = NULL;
4610 curproxy->iface_len = 0;
4611
Willy Tarreaud5191e72010-02-09 20:50:45 +01004612 sk = str2sa(args[1]);
4613 if (!sk) {
4614 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
4617 }
4618 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004620
4621 cur_arg = 2;
4622 while (*(args[cur_arg])) {
4623 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004624#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4625#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004626 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4627 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4628 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 }
4632#endif
4633 if (!*args[cur_arg + 1]) {
4634 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4635 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004638 }
4639
4640 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004641 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004642 curproxy->options |= PR_O_TPXY_CLI;
4643 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004644 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004645 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004646 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4647 char *name, *end;
4648
4649 name = args[cur_arg+1] + 7;
4650 while (isspace(*name))
4651 name++;
4652
4653 end = name;
4654 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4655 end++;
4656
4657 curproxy->options &= ~PR_O_TPXY_MASK;
4658 curproxy->options |= PR_O_TPXY_DYN;
4659 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4660 curproxy->bind_hdr_len = end - name;
4661 memcpy(curproxy->bind_hdr_name, name, end - name);
4662 curproxy->bind_hdr_name[end-name] = '\0';
4663 curproxy->bind_hdr_occ = -1;
4664
4665 /* now look for an occurrence number */
4666 while (isspace(*end))
4667 end++;
4668 if (*end == ',') {
4669 end++;
4670 name = end;
4671 if (*end == '-')
4672 end++;
4673 while (isdigit(*end))
4674 end++;
4675 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4676 }
4677
4678 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4679 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4680 " occurrences values smaller than %d.\n",
4681 file, linenum, MAX_HDR_HISTORY);
4682 err_code |= ERR_ALERT | ERR_FATAL;
4683 goto out;
4684 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004685 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004686 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004687 if (!sk) {
4688 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
4692 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004694 }
4695 global.last_checks |= LSTCHK_NETADM;
4696#if !defined(CONFIG_HAP_LINUX_TPROXY)
4697 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004698#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699#else /* no TPROXY support */
4700 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004701 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004702 err_code |= ERR_ALERT | ERR_FATAL;
4703 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004704#endif
4705 cur_arg += 2;
4706 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004707 }
4708
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004709 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4710#ifdef SO_BINDTODEVICE
4711 if (!*args[cur_arg + 1]) {
4712 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4713 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004716 }
4717 if (curproxy->iface_name)
4718 free(curproxy->iface_name);
4719
4720 curproxy->iface_name = strdup(args[cur_arg + 1]);
4721 curproxy->iface_len = strlen(curproxy->iface_name);
4722 global.last_checks |= LSTCHK_NETADM;
4723#else
4724 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4725 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004728#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004729 cur_arg += 2;
4730 continue;
4731 }
4732 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4733 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004738 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4739 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4740 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751
4752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4753 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004754 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4760 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004761 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], NULL, (const char **)args+2);
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], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_PASS, 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], "reqallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004786 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02004792 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004793 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4795 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004796 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004798 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004799 }
4800 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4802 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004803 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004805 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004806 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4810 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814
4815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4816 ACL_DIR_REQ, ACT_REPLACE, 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 Tarreaubaaee002006-06-26 02:48:02 +02004820 }
4821 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4823 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004824 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
4828 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], NULL, (const char **)args+2);
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], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_PASS, 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], "reqiallow")) { /* allow 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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004849 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4851 ACL_DIR_REQ, ACT_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02004855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004857 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004858
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 if (curproxy == &defproxy) {
4860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004864 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004865 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 if (*(args[1]) == 0) {
4868 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004872
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004873 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4874 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4875 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4876 file, linenum, args[0]);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4881 }
4882 else if (*args[2]) {
4883 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4884 file, linenum, args[0], args[2]);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
4888
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004889 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004890 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004891 wl->s = strdup(args[1]);
4892 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004893 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4898 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004902
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4904 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004905 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004906 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4911 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004912 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4918 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004919 args[0], args[1], NULL, (const char **)args+2);
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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4926 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4932 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004933 args[0], args[1], args[2], (const char **)args+3);
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], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4939 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004940 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4946 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004947 args[0], args[1], NULL, (const char **)args+2);
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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004952 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004953
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 if (curproxy == &defproxy) {
4955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004959 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 if (*(args[1]) == 0) {
4963 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004968 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4969 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4970 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4971 file, linenum, args[0]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975 err_code |= warnif_cond_requires_req(cond, file, linenum);
4976 }
4977 else if (*args[2]) {
4978 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4979 file, linenum, args[0], args[2]);
4980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
4983
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004984 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004985 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004986 wl->s = strdup(args[1]);
4987 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
4989 else if (!strcmp(args[0], "errorloc") ||
4990 !strcmp(args[0], "errorloc302") ||
4991 !strcmp(args[0], "errorloc303")) { /* error location */
4992 int errnum, errlen;
4993 char *err;
4994
Willy Tarreau977b8e42006-12-29 14:19:17 +01004995 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004997
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004999 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
5003
5004 errnum = atol(args[1]);
5005 if (!strcmp(args[0], "errorloc303")) {
5006 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5007 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5008 } else {
5009 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5010 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5011 }
5012
Willy Tarreau0f772532006-12-23 20:51:41 +01005013 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5014 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005015 chunk_destroy(&curproxy->errmsg[rc]);
5016 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005017 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005020
5021 if (rc >= HTTP_ERR_SIZE) {
5022 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5023 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 free(err);
5025 }
5026 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005027 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5028 int errnum, errlen, fd;
5029 char *err;
5030 struct stat stat;
5031
5032 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005034
5035 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005036 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005039 }
5040
5041 fd = open(args[2], O_RDONLY);
5042 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5043 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5044 file, linenum, args[2], args[1]);
5045 if (fd >= 0)
5046 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005049 }
5050
Willy Tarreau27a674e2009-08-17 07:23:33 +02005051 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005052 errlen = stat.st_size;
5053 } else {
5054 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005055 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005057 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005058 }
5059
5060 err = malloc(errlen); /* malloc() must succeed during parsing */
5061 errnum = read(fd, err, errlen);
5062 if (errnum != errlen) {
5063 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5064 file, linenum, args[2], args[1]);
5065 close(fd);
5066 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069 }
5070 close(fd);
5071
5072 errnum = atol(args[1]);
5073 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5074 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005075 chunk_destroy(&curproxy->errmsg[rc]);
5076 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005077 break;
5078 }
5079 }
5080
5081 if (rc >= HTTP_ERR_SIZE) {
5082 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5083 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005085 free(err);
5086 }
5087 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005088 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005089 struct cfg_kw_list *kwl;
5090 int index;
5091
5092 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5093 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5094 if (kwl->kw[index].section != CFG_LISTEN)
5095 continue;
5096 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5097 /* prepare error message just in case */
5098 snprintf(trash, sizeof(trash),
5099 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005100 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5101 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005102 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005105 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005106 else if (rc > 0) {
5107 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_WARN;
5109 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005110 }
Willy Tarreau93893792009-07-23 13:19:11 +02005111 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005112 }
5113 }
5114 }
5115
Willy Tarreau6daf3432008-01-22 16:44:08 +01005116 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
Willy Tarreau93893792009-07-23 13:19:11 +02005120 out:
5121 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122}
5123
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005124int
5125cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5126{
5127
5128 int err_code = 0;
5129 const char *err;
5130
5131 if (!strcmp(args[0], "userlist")) { /* new userlist */
5132 struct userlist *newul;
5133
5134 if (!*args[1]) {
5135 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5136 file, linenum, args[0]);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140
5141 err = invalid_char(args[1]);
5142 if (err) {
5143 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5144 file, linenum, *err, args[0], args[1]);
5145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
5147 }
5148
5149 for (newul = userlist; newul; newul = newul->next)
5150 if (!strcmp(newul->name, args[1])) {
5151 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5152 file, linenum, args[1]);
5153 err_code |= ERR_WARN;
5154 goto out;
5155 }
5156
5157 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5158 if (!newul) {
5159 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5160 err_code |= ERR_ALERT | ERR_ABORT;
5161 goto out;
5162 }
5163
5164 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5165 newul->name = strdup(args[1]);
5166
5167 if (!newul->groupusers | !newul->name) {
5168 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5169 err_code |= ERR_ALERT | ERR_ABORT;
5170 goto out;
5171 }
5172
5173 newul->next = userlist;
5174 userlist = newul;
5175
5176 } else if (!strcmp(args[0], "group")) { /* new group */
5177 int cur_arg, i;
5178 const char *err;
5179
5180 if (!*args[1]) {
5181 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5182 file, linenum, args[0]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186
5187 err = invalid_char(args[1]);
5188 if (err) {
5189 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5190 file, linenum, *err, args[0], args[1]);
5191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
5193 }
5194
5195 for(i = 0; i < userlist->grpcnt; i++)
5196 if (!strcmp(userlist->groups[i], args[1])) {
5197 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5198 file, linenum, args[1], userlist->name);
5199 err_code |= ERR_ALERT;
5200 goto out;
5201 }
5202
5203 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5204 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5205 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209
5210 cur_arg = 2;
5211
5212 while (*args[cur_arg]) {
5213 if (!strcmp(args[cur_arg], "users")) {
5214 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5215 cur_arg += 2;
5216 continue;
5217 } else {
5218 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5219 file, linenum, args[0]);
5220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
5222 }
5223 }
5224
5225 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5226 } else if (!strcmp(args[0], "user")) { /* new user */
5227 struct auth_users *newuser;
5228 int cur_arg;
5229
5230 if (!*args[1]) {
5231 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5232 file, linenum, args[0]);
5233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
5235 }
5236
5237 for (newuser = userlist->users; newuser; newuser = newuser->next)
5238 if (!strcmp(newuser->user, args[1])) {
5239 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5240 file, linenum, args[1], userlist->name);
5241 err_code |= ERR_ALERT;
5242 goto out;
5243 }
5244
5245 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5246 if (!newuser) {
5247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5248 err_code |= ERR_ALERT | ERR_ABORT;
5249 goto out;
5250 }
5251
5252 newuser->user = strdup(args[1]);
5253
5254 newuser->next = userlist->users;
5255 userlist->users = newuser;
5256
5257 cur_arg = 2;
5258
5259 while (*args[cur_arg]) {
5260 if (!strcmp(args[cur_arg], "password")) {
5261#ifndef CONFIG_HAP_CRYPT
5262 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5263 file, linenum);
5264 err_code |= ERR_ALERT;
5265#endif
5266 newuser->pass = strdup(args[cur_arg + 1]);
5267 cur_arg += 2;
5268 continue;
5269 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5270 newuser->pass = strdup(args[cur_arg + 1]);
5271 newuser->flags |= AU_O_INSECURE;
5272 cur_arg += 2;
5273 continue;
5274 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005275 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005276 cur_arg += 2;
5277 continue;
5278 } else {
5279 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5280 file, linenum, args[0]);
5281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
5283 }
5284 }
5285 } else {
5286 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5287 err_code |= ERR_ALERT | ERR_FATAL;
5288 }
5289
5290out:
5291 return err_code;
5292}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293
5294/*
5295 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005296 * Returns the error code, 0 if OK, or any combination of :
5297 * - ERR_ABORT: must abort ASAP
5298 * - ERR_FATAL: we can continue parsing but not start the service
5299 * - ERR_WARN: a warning has been emitted
5300 * - ERR_ALERT: an alert has been emitted
5301 * Only the two first ones can stop processing, the two others are just
5302 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005304int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005306 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307 FILE *f;
5308 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005310 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 if ((f=fopen(file,"r")) == NULL)
5313 return -1;
5314
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005315 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005316 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005317 char *end;
5318 char *args[MAX_LINE_ARGS + 1];
5319 char *line = thisline;
5320
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 linenum++;
5322
5323 end = line + strlen(line);
5324
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005325 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5326 /* Check if we reached the limit and the last char is not \n.
5327 * Watch out for the last line without the terminating '\n'!
5328 */
5329 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005330 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005331 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005332 }
5333
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005335 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 line++;
5337
5338 arg = 0;
5339 args[arg] = line;
5340
5341 while (*line && arg < MAX_LINE_ARGS) {
5342 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5343 * C equivalent value. Other combinations left unchanged (eg: \1).
5344 */
5345 if (*line == '\\') {
5346 int skip = 0;
5347 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5348 *line = line[1];
5349 skip = 1;
5350 }
5351 else if (line[1] == 'r') {
5352 *line = '\r';
5353 skip = 1;
5354 }
5355 else if (line[1] == 'n') {
5356 *line = '\n';
5357 skip = 1;
5358 }
5359 else if (line[1] == 't') {
5360 *line = '\t';
5361 skip = 1;
5362 }
5363 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005364 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 unsigned char hex1, hex2;
5366 hex1 = toupper(line[2]) - '0';
5367 hex2 = toupper(line[3]) - '0';
5368 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5369 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5370 *line = (hex1<<4) + hex2;
5371 skip = 3;
5372 }
5373 else {
5374 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005375 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
5377 }
5378 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005379 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 end -= skip;
5381 }
5382 line++;
5383 }
5384 else if (*line == '#' || *line == '\n' || *line == '\r') {
5385 /* end of string, end of loop */
5386 *line = 0;
5387 break;
5388 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005389 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005390 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005391 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005392 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 line++;
5394 args[++arg] = line;
5395 }
5396 else {
5397 line++;
5398 }
5399 }
5400
5401 /* empty line */
5402 if (!**args)
5403 continue;
5404
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005405 if (*line) {
5406 /* we had to stop due to too many args.
5407 * Let's terminate the string, print the offending part then cut the
5408 * last arg.
5409 */
5410 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5411 line++;
5412 *line = '\0';
5413
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005414 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005415 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005416 err_code |= ERR_ALERT | ERR_FATAL;
5417 args[arg] = line;
5418 }
5419
Willy Tarreau540abe42007-05-02 20:50:16 +02005420 /* zero out remaining args and ensure that at least one entry
5421 * is zeroed out.
5422 */
5423 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 args[arg] = line;
5425 }
5426
Willy Tarreau3842f002009-06-14 11:39:52 +02005427 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005428 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005429 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005430 for (arg=0; *args[arg+1]; arg++)
5431 args[arg] = args[arg+1]; // shift args after inversion
5432 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005433 else if (!strcmp(args[0], "default")) {
5434 kwm = KWM_DEF;
5435 for (arg=0; *args[arg+1]; arg++)
5436 args[arg] = args[arg+1]; // shift args after inversion
5437 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005438
Willy Tarreau3842f002009-06-14 11:39:52 +02005439 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5440 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005441 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005442 }
5443
Willy Tarreau977b8e42006-12-29 14:19:17 +01005444 if (!strcmp(args[0], "listen") ||
5445 !strcmp(args[0], "frontend") ||
5446 !strcmp(args[0], "backend") ||
5447 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005448 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005450 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005451 cursection = strdup(args[0]);
5452 }
5453 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005455 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005456 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005457 }
5458 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005459 confsect = CFG_USERLIST;
5460 free(cursection);
5461 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005462 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005463 else if (!strcmp(args[0], "peers")) {
5464 confsect = CFG_PEERS;
5465 free(cursection);
5466 cursection = strdup(args[0]);
5467 }
5468
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 /* else it's a section keyword */
5470
5471 switch (confsect) {
5472 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474 break;
5475 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005476 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005478 case CFG_USERLIST:
5479 err_code |= cfg_parse_users(file, linenum, args, kwm);
5480 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005481 case CFG_PEERS:
5482 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5483 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005485 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005486 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005488
5489 if (err_code & ERR_ABORT)
5490 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005492 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005493 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005495 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005496}
5497
Willy Tarreaubb925012009-07-23 13:36:36 +02005498/*
5499 * Returns the error code, 0 if OK, or any combination of :
5500 * - ERR_ABORT: must abort ASAP
5501 * - ERR_FATAL: we can continue parsing but not start the service
5502 * - ERR_WARN: a warning has been emitted
5503 * - ERR_ALERT: an alert has been emitted
5504 * Only the two first ones can stop processing, the two others are just
5505 * indicators.
5506 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005507int check_config_validity()
5508{
5509 int cfgerr = 0;
5510 struct proxy *curproxy = NULL;
5511 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005512 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005513 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005514 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515
5516 /*
5517 * Now, check for the integrity of all that we have collected.
5518 */
5519
5520 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005521 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005523 /* first, we will invert the proxy list order */
5524 curproxy = NULL;
5525 while (proxy) {
5526 struct proxy *next;
5527
5528 next = proxy->next;
5529 proxy->next = curproxy;
5530 curproxy = proxy;
5531 if (!next)
5532 break;
5533 proxy = next;
5534 }
5535
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005537 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 }
5541
5542 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005543 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005544 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005545 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005546 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005547 unsigned int next_id;
5548
5549 if (!curproxy->uuid) {
5550 /* proxy ID not set, use automatic numbering with first
5551 * spare entry starting with next_pxid.
5552 */
5553 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5554 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5555 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005556 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005557 next_pxid++;
5558
Willy Tarreau55ea7572007-06-17 19:56:27 +02005559
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005561 /* ensure we don't keep listeners uselessly bound */
5562 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 curproxy = curproxy->next;
5564 continue;
5565 }
5566
Willy Tarreauff01a212009-03-15 13:46:16 +01005567 switch (curproxy->mode) {
5568 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005569 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005570 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005571 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5572 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005573 cfgerr++;
5574 }
5575
5576 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005577 Warning("config : servers will be ignored for %s '%s'.\n",
5578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 break;
5580
5581 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005582 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005583 break;
5584
5585 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005586 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005587 break;
5588 }
5589
5590 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005591 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5592 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 cfgerr++;
5594 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005595
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005596 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005597 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005598 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005599 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5600 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005601 cfgerr++;
5602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005604 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005605 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5606 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005607 cfgerr++;
5608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005610 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005611 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5612 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005613 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005614 }
5615 }
5616 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005617 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 /* If no LB algo is set in a backend, and we're not in
5619 * transparent mode, dispatch mode nor proxy mode, we
5620 * want to use balance roundrobin by default.
5621 */
5622 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5623 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 }
5625 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005626
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005627 if (curproxy->options2 & PR_O2_DISPATCH) {
5628 curproxy->options &= ~PR_O_TRANSP;
5629 curproxy->options &= ~PR_O_HTTP_PROXY;
5630 }
5631 else if (curproxy->options & PR_O_HTTP_PROXY) {
5632 curproxy->options2 &= ~PR_O2_DISPATCH;
5633 curproxy->options &= ~PR_O_TRANSP;
5634 }
5635 else if (curproxy->options & PR_O_TRANSP) {
5636 curproxy->options2 &= ~PR_O2_DISPATCH;
5637 curproxy->options &= ~PR_O_HTTP_PROXY;
5638 }
5639
Willy Tarreau82936582007-11-30 15:20:09 +01005640 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5641 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005642 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5643 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005644 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005645 }
5646
Willy Tarreauef781042010-01-27 11:53:01 +01005647 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5648 curproxy->options &= ~PR_O2_CHK_SNDST;
5649 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5650 "send-state", proxy_type_str(curproxy), curproxy->id);
5651 err_code |= ERR_WARN;
5652 }
5653
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005654 /* if a default backend was specified, let's find it */
5655 if (curproxy->defbe.name) {
5656 struct proxy *target;
5657
Alex Williams96532db2009-11-01 21:27:13 -05005658 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005659 if (!target) {
5660 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5661 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005662 cfgerr++;
5663 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005664 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5665 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005666 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005667 } else {
5668 free(curproxy->defbe.name);
5669 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005670 /* we force the backend to be present on at least all of
5671 * the frontend's processes.
5672 */
5673 target->bind_proc = curproxy->bind_proc ?
5674 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
5676 }
5677
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005678 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005679 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5680 /* map jump target for ACT_SETBE in req_rep chain */
5681 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005682 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005683 struct proxy *target;
5684
Willy Tarreaua496b602006-12-17 23:15:24 +01005685 if (exp->action != ACT_SETBE)
5686 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005687
Alex Williams96532db2009-11-01 21:27:13 -05005688 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005689 if (!target) {
5690 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5691 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005692 cfgerr++;
5693 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005694 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5695 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005696 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005697 } else {
5698 free((void *)exp->replace);
5699 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005700 /* we force the backend to be present on at least all of
5701 * the frontend's processes.
5702 */
5703 target->bind_proc = curproxy->bind_proc ?
5704 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005705 }
5706 }
5707 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708
5709 /* find the target proxy for 'use_backend' rules */
5710 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005711 struct proxy *target;
5712
Alex Williams96532db2009-11-01 21:27:13 -05005713 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005714
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005715 if (!target) {
5716 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5717 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005718 cfgerr++;
5719 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005720 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5721 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005722 cfgerr++;
5723 } else {
5724 free((void *)rule->be.name);
5725 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005726 /* we force the backend to be present on at least all of
5727 * the frontend's processes.
5728 */
5729 target->bind_proc = curproxy->bind_proc ?
5730 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005731 }
5732 }
5733
Emeric Brunb982a3d2010-01-04 15:45:53 +01005734 /* find the target table for 'stick' rules */
5735 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5736 struct proxy *target;
5737
Emeric Brun1d33b292010-01-04 15:47:17 +01005738 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5739 if (mrule->flags & STK_IS_STORE)
5740 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5741
Emeric Brunb982a3d2010-01-04 15:45:53 +01005742 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005743 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005744 else
5745 target = curproxy;
5746
5747 if (!target) {
5748 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5749 curproxy->id, mrule->table.name);
5750 cfgerr++;
5751 }
5752 else if (target->table.size == 0) {
5753 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5755 cfgerr++;
5756 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005757 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005758 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5759 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5760 cfgerr++;
5761 }
5762 else {
5763 free((void *)mrule->table.name);
5764 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005765 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005766 }
5767 }
5768
5769 /* find the target table for 'store response' rules */
5770 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5771 struct proxy *target;
5772
Emeric Brun1d33b292010-01-04 15:47:17 +01005773 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5774
Emeric Brunb982a3d2010-01-04 15:45:53 +01005775 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005776 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 else
5778 target = curproxy;
5779
5780 if (!target) {
5781 Alert("Proxy '%s': unable to find store table '%s'.\n",
5782 curproxy->id, mrule->table.name);
5783 cfgerr++;
5784 }
5785 else if (target->table.size == 0) {
5786 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5788 cfgerr++;
5789 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005790 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005791 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5792 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5793 cfgerr++;
5794 }
5795 else {
5796 free((void *)mrule->table.name);
5797 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005798 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005799 }
5800 }
5801
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005802 /* find the target table for 'tcp-request' layer 4 rules */
5803 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5804 struct proxy *target;
5805
Willy Tarreau56123282010-08-06 19:06:56 +02005806 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005807 continue;
5808
5809 if (trule->act_prm.trk_ctr.table.n)
5810 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5811 else
5812 target = curproxy;
5813
5814 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005815 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5816 curproxy->id, trule->act_prm.trk_ctr.table.n,
5817 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005818 cfgerr++;
5819 }
5820 else if (target->table.size == 0) {
5821 Alert("Proxy '%s': table '%s' used but not configured.\n",
5822 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5823 cfgerr++;
5824 }
5825 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005826 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 +02005827 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5828 cfgerr++;
5829 }
5830 else {
5831 free(trule->act_prm.trk_ctr.table.n);
5832 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005833 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005834 * to pass a list of counters to track and allocate them right here using
5835 * stktable_alloc_data_type().
5836 */
5837 }
5838 }
5839
Willy Tarreaud1f96522010-08-03 19:34:32 +02005840 /* find the target table for 'tcp-request' layer 6 rules */
5841 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5842 struct proxy *target;
5843
Willy Tarreau56123282010-08-06 19:06:56 +02005844 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005845 continue;
5846
5847 if (trule->act_prm.trk_ctr.table.n)
5848 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5849 else
5850 target = curproxy;
5851
5852 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005853 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5854 curproxy->id, trule->act_prm.trk_ctr.table.n,
5855 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005856 cfgerr++;
5857 }
5858 else if (target->table.size == 0) {
5859 Alert("Proxy '%s': table '%s' used but not configured.\n",
5860 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5861 cfgerr++;
5862 }
5863 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005864 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 +02005865 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5866 cfgerr++;
5867 }
5868 else {
5869 free(trule->act_prm.trk_ctr.table.n);
5870 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005871 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005872 * to pass a list of counters to track and allocate them right here using
5873 * stktable_alloc_data_type().
5874 */
5875 }
5876 }
5877
Emeric Brun32da3c42010-09-23 18:39:19 +02005878 if (curproxy->table.peers.name) {
5879 struct peers *curpeers = peers;
5880
5881 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5882 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5883 free((void *)curproxy->table.peers.name);
5884 curproxy->table.peers.p = peers;
5885 break;
5886 }
5887 }
5888
5889 if (!curpeers) {
5890 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5891 curproxy->id, curproxy->table.peers.name);
5892 cfgerr++;
5893 }
5894 else if (!curpeers->peers_fe) {
5895 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5896 curproxy->id, curpeers->id);
5897 cfgerr++;
5898 }
5899 }
5900
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005901 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005902 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005903 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5904 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5905 "proxy", curproxy->id);
5906 cfgerr++;
5907 goto out_uri_auth_compat;
5908 }
5909
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005910 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005911 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005912 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005913 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914
Willy Tarreau95fa4692010-02-01 13:05:50 +01005915 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5916 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005917
5918 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005919 uri_auth_compat_req[i++] = "realm";
5920 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5921 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005922
Willy Tarreau95fa4692010-02-01 13:05:50 +01005923 uri_auth_compat_req[i++] = "unless";
5924 uri_auth_compat_req[i++] = "{";
5925 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5926 uri_auth_compat_req[i++] = "}";
5927 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005928
Willy Tarreauff011f22011-01-06 17:51:27 +01005929 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5930 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005931 cfgerr++;
5932 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005933 }
5934
Willy Tarreauff011f22011-01-06 17:51:27 +01005935 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005936
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005937 if (curproxy->uri_auth->auth_realm) {
5938 free(curproxy->uri_auth->auth_realm);
5939 curproxy->uri_auth->auth_realm = NULL;
5940 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005941
5942 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005943 }
5944out_uri_auth_compat:
5945
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005946 cfgerr += acl_find_targets(curproxy);
5947
Willy Tarreau2738a142006-07-08 17:28:09 +02005948 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005949 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005950 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005951 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005952 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005953 " | While not properly invalid, you will certainly encounter various problems\n"
5954 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005955 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005956 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005957 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005958 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005959
Willy Tarreau1fa31262007-12-03 00:36:16 +01005960 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5961 * We must still support older configurations, so let's find out whether those
5962 * parameters have been set or must be copied from contimeouts.
5963 */
5964 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005965 if (!curproxy->timeout.tarpit ||
5966 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005967 /* tarpit timeout not set. We search in the following order:
5968 * default.tarpit, curr.connect, default.connect.
5969 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005970 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005971 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005972 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005973 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005974 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005975 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005976 }
5977 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005978 (!curproxy->timeout.queue ||
5979 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005980 /* queue timeout not set. We search in the following order:
5981 * default.queue, curr.connect, default.connect.
5982 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005983 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005984 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005985 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005986 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005987 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005988 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005989 }
5990 }
5991
Willy Tarreau07a54902010-03-29 18:33:29 +02005992 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005993 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5994 curproxy->check_req = (char *)malloc(curproxy->check_len);
5995 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005996 }
5997
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005998 /* The small pools required for the capture lists */
5999 if (curproxy->nb_req_cap)
6000 curproxy->req_cap_pool = create_pool("ptrcap",
6001 curproxy->nb_req_cap * sizeof(char *),
6002 MEM_F_SHARED);
6003 if (curproxy->nb_rsp_cap)
6004 curproxy->rsp_cap_pool = create_pool("ptrcap",
6005 curproxy->nb_rsp_cap * sizeof(char *),
6006 MEM_F_SHARED);
6007
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006008 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6009 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6010 MEM_F_SHARED);
6011
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 /* first, we will invert the servers list order */
6013 newsrv = NULL;
6014 while (curproxy->srv) {
6015 struct server *next;
6016
6017 next = curproxy->srv->next;
6018 curproxy->srv->next = newsrv;
6019 newsrv = curproxy->srv;
6020 if (!next)
6021 break;
6022 curproxy->srv = next;
6023 }
6024
Willy Tarreaudd701652010-05-25 23:03:02 +02006025 /* assign automatic UIDs to servers which don't have one yet */
6026 next_id = 1;
6027 newsrv = curproxy->srv;
6028 while (newsrv != NULL) {
6029 if (!newsrv->puid) {
6030 /* server ID not set, use automatic numbering with first
6031 * spare entry starting with next_svid.
6032 */
6033 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6034 newsrv->conf.id.key = newsrv->puid = next_id;
6035 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6036 }
6037 next_id++;
6038 newsrv = newsrv->next;
6039 }
6040
Willy Tarreau20697042007-11-15 23:26:18 +01006041 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006042 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006044 /* We have to initialize the server lookup mechanism depending
6045 * on what LB algorithm was choosen.
6046 */
6047
6048 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6049 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6050 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006051 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6052 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6053 init_server_map(curproxy);
6054 } else {
6055 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6056 fwrr_init_server_groups(curproxy);
6057 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006058 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006059
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006060 case BE_LB_KIND_LC:
6061 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006062 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006063 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006064
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006065 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006066 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6067 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6068 chash_init_server_tree(curproxy);
6069 } else {
6070 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6071 init_server_map(curproxy);
6072 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006073 break;
6074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075
6076 if (curproxy->options & PR_O_LOGASAP)
6077 curproxy->to_log &= ~LW_BYTES;
6078
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006079 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6080 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6081 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6082 proxy_type_str(curproxy), curproxy->id);
6083 err_code |= ERR_WARN;
6084 }
6085
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006086 if (curproxy->mode != PR_MODE_HTTP) {
6087 int optnum;
6088
6089 if (curproxy->options & PR_O_COOK_ANY) {
6090 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6091 proxy_type_str(curproxy), curproxy->id);
6092 err_code |= ERR_WARN;
6093 }
6094
6095 if (curproxy->uri_auth) {
6096 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6097 proxy_type_str(curproxy), curproxy->id);
6098 err_code |= ERR_WARN;
6099 curproxy->uri_auth = NULL;
6100 }
6101
6102 if (curproxy->options & PR_O_FWDFOR) {
6103 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6104 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6105 err_code |= ERR_WARN;
6106 curproxy->options &= ~PR_O_FWDFOR;
6107 }
6108
6109 if (curproxy->options & PR_O_ORGTO) {
6110 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6111 "originalto", proxy_type_str(curproxy), curproxy->id);
6112 err_code |= ERR_WARN;
6113 curproxy->options &= ~PR_O_ORGTO;
6114 }
6115
6116 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6117 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6118 (curproxy->cap & cfg_opts[optnum].cap) &&
6119 (curproxy->options & cfg_opts[optnum].val)) {
6120 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6121 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6122 err_code |= ERR_WARN;
6123 curproxy->options &= ~cfg_opts[optnum].val;
6124 }
6125 }
6126
6127 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6128 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6129 (curproxy->cap & cfg_opts2[optnum].cap) &&
6130 (curproxy->options2 & cfg_opts2[optnum].val)) {
6131 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6132 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6133 err_code |= ERR_WARN;
6134 curproxy->options2 &= ~cfg_opts2[optnum].val;
6135 }
6136 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006137
Willy Tarreauefa5f512010-03-30 20:13:29 +02006138#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006139 if (curproxy->bind_hdr_occ) {
6140 curproxy->bind_hdr_occ = 0;
6141 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6142 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6143 err_code |= ERR_WARN;
6144 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006145#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006146 }
6147
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006149 * ensure that we're not cross-dressing a TCP server into HTTP.
6150 */
6151 newsrv = curproxy->srv;
6152 while (newsrv != NULL) {
6153 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006154 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6155 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006156 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006157 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006158
Willy Tarreauefa5f512010-03-30 20:13:29 +02006159#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006160 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6161 newsrv->bind_hdr_occ = 0;
6162 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6163 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6164 err_code |= ERR_WARN;
6165 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006166#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006167 newsrv = newsrv->next;
6168 }
6169
6170 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 * If this server supports a maxconn parameter, it needs a dedicated
6172 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006173 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 */
6175 newsrv = curproxy->srv;
6176 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006177 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 /* Only 'minconn' was specified, or it was higher than or equal
6179 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6180 * this will avoid further useless expensive computations.
6181 */
6182 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006183 } else if (newsrv->maxconn && !newsrv->minconn) {
6184 /* minconn was not specified, so we set it to maxconn */
6185 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006186 }
6187
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006188 if (newsrv->trackit) {
6189 struct proxy *px;
6190 struct server *srv;
6191 char *pname, *sname;
6192
6193 pname = newsrv->trackit;
6194 sname = strrchr(pname, '/');
6195
6196 if (sname)
6197 *sname++ = '\0';
6198 else {
6199 sname = pname;
6200 pname = NULL;
6201 }
6202
6203 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006204 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006206 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6207 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006208 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006209 cfgerr++;
6210 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006211 }
6212 } else
6213 px = curproxy;
6214
6215 srv = findserver(px, sname);
6216 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6218 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006219 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006220 cfgerr++;
6221 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006222 }
6223
6224 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006225 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006226 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006227 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006229 cfgerr++;
6230 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 }
6232
6233 if (curproxy != px &&
6234 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006235 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006236 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006237 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006238 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006239 cfgerr++;
6240 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006241 }
6242
6243 newsrv->tracked = srv;
6244 newsrv->tracknext = srv->tracknext;
6245 srv->tracknext = newsrv;
6246
6247 free(newsrv->trackit);
6248 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006249 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006250 newsrv = newsrv->next;
6251 }
6252
Willy Tarreauc1a21672009-08-16 22:37:44 +02006253 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006254 curproxy->accept = frontend_accept;
6255
Willy Tarreauc1a21672009-08-16 22:37:44 +02006256 if (curproxy->tcp_req.inspect_delay ||
6257 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006258 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006259
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006260 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006261 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006262 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006263 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006264
6265 /* both TCP and HTTP must check switching rules */
6266 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6267 }
6268
6269 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006270 if (curproxy->tcp_req.inspect_delay ||
6271 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6272 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6273
Emeric Brun97679e72010-09-23 17:56:44 +02006274 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6275 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6276
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006277 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006278 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006279 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006280 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006281
6282 /* If the backend does requires RDP cookie persistence, we have to
6283 * enable the corresponding analyser.
6284 */
6285 if (curproxy->options2 & PR_O2_RDPC_PRST)
6286 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6287 }
6288
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006289 listener = NULL;
6290 while (curproxy->listen) {
6291 struct listener *next;
6292
6293 next = curproxy->listen->next;
6294 curproxy->listen->next = listener;
6295 listener = curproxy->listen;
6296
6297 if (!next)
6298 break;
6299
6300 curproxy->listen = next;
6301 }
6302
Willy Tarreaue6b98942007-10-29 01:09:36 +01006303 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006304 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006305 listener = curproxy->listen;
6306 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006307 if (!listener->luid) {
6308 /* listener ID not set, use automatic numbering with first
6309 * spare entry starting with next_luid.
6310 */
6311 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6312 listener->conf.id.key = listener->luid = next_id;
6313 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006314 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006315 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006316
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006317 /* enable separate counters */
6318 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6319 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6320 if (!listener->name) {
6321 sprintf(trash, "sock-%d", listener->luid);
6322 listener->name = strdup(trash);
6323 }
6324 }
6325
Willy Tarreaue6b98942007-10-29 01:09:36 +01006326 if (curproxy->options & PR_O_TCP_NOLING)
6327 listener->options |= LI_O_NOLINGER;
6328 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006329 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006330 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006331 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006332 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006333 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006334 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006335
Willy Tarreau8a956912010-10-15 14:27:08 +02006336 if (listener->options & LI_O_ACC_PROXY)
6337 listener->analysers |= AN_REQ_DECODE_PROXY;
6338
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006339 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6340 listener->options |= LI_O_TCP_RULES;
6341
Willy Tarreaude3041d2010-05-31 10:56:17 +02006342 if (curproxy->mon_mask.s_addr)
6343 listener->options |= LI_O_CHK_MONNET;
6344
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006345 /* smart accept mode is automatic in HTTP mode */
6346 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6347 (curproxy->mode == PR_MODE_HTTP &&
6348 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6349 listener->options |= LI_O_NOQUICKACK;
6350
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006351 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006352 listener = listener->next;
6353 }
6354
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006355 /* Check multi-process mode compatibility for the current proxy */
6356 if (global.nbproc > 1) {
6357 int nbproc = 0;
6358 if (curproxy->bind_proc) {
6359 int proc;
6360 for (proc = 0; proc < global.nbproc; proc++) {
6361 if (curproxy->bind_proc & (1 << proc)) {
6362 nbproc++;
6363 }
6364 }
6365 } else {
6366 nbproc = global.nbproc;
6367 }
6368 if (curproxy->table.peers.name) {
6369 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6370 curproxy->id);
6371 cfgerr++;
6372 }
6373 if (nbproc > 1) {
6374 if (curproxy->uri_auth) {
6375 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6376 curproxy->id);
6377 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6378 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6379 curproxy->id);
6380 }
6381 }
6382 if (curproxy->appsession_name) {
6383 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6384 curproxy->id);
6385 }
6386 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6387 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6388 curproxy->id);
6389 }
6390 }
6391 }
6392
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 curproxy = curproxy->next;
6394 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006395
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006396 /* Check multi-process mode compatibility */
6397 if (global.nbproc > 1) {
6398 if (global.stats_fe) {
6399 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6400 }
6401 }
6402
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006403 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6404 struct auth_users *curuser;
6405 int g;
6406
6407 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6408 unsigned int group_mask = 0;
6409 char *group = NULL;
6410
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006411 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006412 continue;
6413
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006414 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006415
6416 for (g = 0; g < curuserlist->grpcnt; g++)
6417 if (!strcmp(curuserlist->groups[g], group))
6418 break;
6419
6420 if (g == curuserlist->grpcnt) {
6421 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6422 curuserlist->name, group, curuser->user);
6423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
6425 }
6426
6427 group_mask |= (1 << g);
6428 }
6429
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006430 free(curuser->u.groups);
6431 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006432 }
6433
6434 for (g = 0; g < curuserlist->grpcnt; g++) {
6435 char *user = NULL;
6436
6437 if (!curuserlist->groupusers[g])
6438 continue;
6439
6440 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6441 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6442 if (!strcmp(curuser->user, user))
6443 break;
6444
6445 if (!curuser) {
6446 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6447 curuserlist->name, user, curuserlist->groups[g]);
6448 err_code |= ERR_ALERT | ERR_FATAL;
6449 goto out;
6450 }
6451
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006452 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006453 }
6454
6455 free(curuserlist->groupusers[g]);
6456 }
6457
6458 free(curuserlist->groupusers);
6459
6460#ifdef DEBUG_AUTH
6461 for (g = 0; g < curuserlist->grpcnt; g++) {
6462 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6463
6464 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6465 if (curuser->group_mask & (1 << g))
6466 fprintf(stderr, " %s", curuser->user);
6467 }
6468
6469 fprintf(stderr, "\n");
6470 }
6471#endif
6472
Willy Tarreaufbb78422011-06-05 15:38:35 +02006473 }
6474
6475 /* automatically compute fullconn if not set. We must not do it in the
6476 * loop above because cross-references are not yet fully resolved.
6477 */
6478 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6479 /* If <fullconn> is not set, let's set it to 10% of the sum of
6480 * the possible incoming frontend's maxconns.
6481 */
6482 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6483 struct proxy *fe;
6484 int total = 0;
6485
6486 /* sum up the number of maxconns of frontends which
6487 * reference this backend at least once or which are
6488 * the same one ('listen').
6489 */
6490 for (fe = proxy; fe; fe = fe->next) {
6491 struct switching_rule *rule;
6492 struct hdr_exp *exp;
6493 int found = 0;
6494
6495 if (!(fe->cap & PR_CAP_FE))
6496 continue;
6497
6498 if (fe == curproxy) /* we're on a "listen" instance */
6499 found = 1;
6500
6501 if (fe->defbe.be == curproxy) /* "default_backend" */
6502 found = 1;
6503
6504 /* check if a "use_backend" rule matches */
6505 if (!found) {
6506 list_for_each_entry(rule, &fe->switching_rules, list) {
6507 if (rule->be.backend == curproxy) {
6508 found = 1;
6509 break;
6510 }
6511 }
6512 }
6513
6514 /* check if a "reqsetbe" rule matches */
6515 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6516 if (exp->action == ACT_SETBE &&
6517 (struct proxy *)exp->replace == curproxy) {
6518 found = 1;
6519 break;
6520 }
6521 }
6522
6523 /* now we've checked all possible ways to reference a backend
6524 * from a frontend.
6525 */
6526 printf("%s checking %s : found=%d\n", curproxy->id, fe->id, found);
6527 if (!found)
6528 continue;
6529 total += fe->maxconn;
6530 printf("px %s adds %d to %s\n", fe->id, fe->maxconn, curproxy->id);
6531 }
6532 printf("%s: total=%d\n", curproxy->id, total);
6533 /* we have the sum of the maxconns in <total>. We only
6534 * keep 10% of that sum to set the default fullconn, with
6535 * a hard minimum of 1 (to avoid a divide by zero).
6536 */
6537 curproxy->fullconn = (total + 9) / 10;
6538 if (!curproxy->fullconn)
6539 curproxy->fullconn = 1;
6540 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006541 }
6542
Willy Tarreau056f5682010-06-06 15:51:11 +02006543 /* initialize stick-tables on backend capable proxies. This must not
6544 * be done earlier because the data size may be discovered while parsing
6545 * other proxies.
6546 */
6547 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006548 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006549
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006550 /*
6551 * Recount currently required checks.
6552 */
6553
6554 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6555 int optnum;
6556
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006557 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6558 if (curproxy->options & cfg_opts[optnum].val)
6559 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006560
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006561 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6562 if (curproxy->options2 & cfg_opts2[optnum].val)
6563 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006564 }
6565
Willy Tarreaubb925012009-07-23 13:36:36 +02006566 if (cfgerr > 0)
6567 err_code |= ERR_ALERT | ERR_FATAL;
6568 out:
6569 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570}
6571
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006572/*
6573 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6574 * parsing sessions.
6575 */
6576void cfg_register_keywords(struct cfg_kw_list *kwl)
6577{
6578 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6579}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006581/*
6582 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6583 */
6584void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6585{
6586 LIST_DEL(&kwl->list);
6587 LIST_INIT(&kwl->list);
6588}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589
6590/*
6591 * Local variables:
6592 * c-indent-level: 8
6593 * c-basic-offset: 8
6594 * End:
6595 */