blob: 1889654d2605016540c2988fe3e7f5c53a1e86a2 [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 Tarreau81c25d02011-09-07 15:17:21 +0200685 else if (!strcmp(args[0], "maxconnrate")) {
686 if (global.cps_lim != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.cps_lim = atol(args[1]);
697 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100698 else if (!strcmp(args[0], "maxpipes")) {
699 if (global.maxpipes != 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 Tarreau3ec79b92009-01-18 20:39:42 +0100703 }
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 Tarreau3ec79b92009-01-18 20:39:42 +0100708 }
709 global.maxpipes = atol(args[1]);
710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200711 else if (!strcmp(args[0], "ulimit-n")) {
712 if (global.rlimit_nofile != 0) {
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 an integer 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.rlimit_nofile = atol(args[1]);
723 }
724 else if (!strcmp(args[0], "chroot")) {
725 if (global.chroot != NULL) {
726 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200727 err_code |= ERR_ALERT;
728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 }
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 global.chroot = strdup(args[1]);
736 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200737 else if (!strcmp(args[0], "description")) {
738 int i, len=0;
739 char *d;
740
741 if (!*args[1]) {
742 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
743 file, linenum, args[0]);
744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
746 }
747
748 for(i=1; *args[i]; i++)
749 len += strlen(args[i])+1;
750
751 if (global.desc)
752 free(global.desc);
753
754 global.desc = d = (char *)calloc(1, len);
755
756 d += sprintf(d, "%s", args[1]);
757 for(i=2; *args[i]; i++)
758 d += sprintf(d, " %s", args[i]);
759 }
760 else if (!strcmp(args[0], "node")) {
761 int i;
762 char c;
763
764 for (i=0; args[1][i]; i++) {
765 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100766 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
767 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200768 break;
769 }
770
771 if (!i || args[1][i]) {
772 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
773 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
774 file, linenum, args[0]);
775 err_code |= ERR_ALERT | ERR_FATAL;
776 goto out;
777 }
778
779 if (global.node)
780 free(global.node);
781
782 global.node = strdup(args[1]);
783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 else if (!strcmp(args[0], "pidfile")) {
785 if (global.pidfile != NULL) {
786 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200787 err_code |= ERR_ALERT;
788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200789 }
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200794 }
795 global.pidfile = strdup(args[1]);
796 }
Emeric Bruned760922010-10-22 17:59:25 +0200797 else if (!strcmp(args[0], "unix-bind")) {
798 int cur_arg = 1;
799 while (*(args[cur_arg])) {
800 if (!strcmp(args[cur_arg], "prefix")) {
801 if (global.unix_bind.prefix != NULL) {
802 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
803 err_code |= ERR_ALERT;
804 cur_arg += 2;
805 continue;
806 }
807
808 if (*(args[cur_arg+1]) == 0) {
809 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
812 }
813 global.unix_bind.prefix = strdup(args[cur_arg+1]);
814 cur_arg += 2;
815 continue;
816 }
817
818 if (!strcmp(args[cur_arg], "mode")) {
819
820 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
821 cur_arg += 2;
822 continue;
823 }
824
825 if (!strcmp(args[cur_arg], "uid")) {
826
827 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
828 cur_arg += 2;
829 continue;
830 }
831
832 if (!strcmp(args[cur_arg], "gid")) {
833
834 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
835 cur_arg += 2;
836 continue;
837 }
838
839 if (!strcmp(args[cur_arg], "user")) {
840 struct passwd *user;
841
842 user = getpwnam(args[cur_arg + 1]);
843 if (!user) {
844 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
845 file, linenum, args[0], args[cur_arg + 1 ]);
846 err_code |= ERR_ALERT | ERR_FATAL;
847 goto out;
848 }
849
850 global.unix_bind.ux.uid = user->pw_uid;
851 cur_arg += 2;
852 continue;
853 }
854
855 if (!strcmp(args[cur_arg], "group")) {
856 struct group *group;
857
858 group = getgrnam(args[cur_arg + 1]);
859 if (!group) {
860 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
861 file, linenum, args[0], args[cur_arg + 1 ]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 global.unix_bind.ux.gid = group->gr_gid;
867 cur_arg += 2;
868 continue;
869 }
870
Willy Tarreaub48f9582011-09-05 01:17:06 +0200871 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200872 file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100878 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200879 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880
881 if (*(args[1]) == 0 || *(args[2]) == 0) {
882 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 }
886
887 facility = get_log_facility(args[2]);
888 if (facility < 0) {
889 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893
894 level = 7; /* max syslog level = debug */
895 if (*(args[3])) {
896 level = get_log_level(args[3]);
897 if (level < 0) {
898 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 err_code |= ERR_ALERT | ERR_FATAL;
900 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 }
902 }
903
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200904 minlvl = 0; /* limit syslog level to this level (emerg) */
905 if (*(args[4])) {
906 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200907 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200908 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200909 err_code |= ERR_ALERT | ERR_FATAL;
910 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200911 }
912 }
913
Robert Tsai81ae1952007-12-05 10:47:29 +0100914 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100915 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100916 if (!sk) {
917 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100918 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100922 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100924 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100925 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100926 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
927 err_code |= ERR_ALERT | ERR_FATAL;
928 goto out;
929 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100930 logsrv.addr = *sk;
931 if (!get_host_port(&logsrv.addr))
932 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100933 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934
935 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100936 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 global.logfac1 = facility;
938 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200939 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 }
941 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100942 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 global.logfac2 = facility;
944 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 }
947 else {
948 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200951 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100952 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
953 char *name;
954 int len;
955
956 if (global.log_send_hostname != NULL) {
957 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT;
959 goto out;
960 }
961
962 if (*(args[1]))
963 name = args[1];
964 else
965 name = hostname;
966
967 len = strlen(name);
968
969 /* We'll add a space after the name to respect the log format */
970 free(global.log_send_hostname);
971 global.log_send_hostname = malloc(len + 2);
972 snprintf(global.log_send_hostname, len + 2, "%s ", name);
973 }
Kevinm48936af2010-12-22 16:08:21 +0000974 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
979 }
980 free(global.log_tag);
981 global.log_tag = strdup(args[1]);
982 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200983 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
984 if (global.spread_checks != 0) {
985 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT;
987 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200988 }
989 if (*(args[1]) == 0) {
990 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT | ERR_FATAL;
992 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200993 }
994 global.spread_checks = atol(args[1]);
995 if (global.spread_checks < 0 || global.spread_checks > 50) {
996 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200997 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 struct cfg_kw_list *kwl;
1002 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001003 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004
1005 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1006 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1007 if (kwl->kw[index].section != CFG_GLOBAL)
1008 continue;
1009 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1010 /* prepare error message just in case */
1011 snprintf(trash, sizeof(trash),
1012 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001013 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1014 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001015 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001017 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001018 else if (rc > 0) {
1019 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001020 err_code |= ERR_WARN;
1021 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001022 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001024 }
1025 }
1026 }
1027
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001031
Willy Tarreau058e9072009-07-20 09:30:05 +02001032 out:
1033 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001034}
1035
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001036void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001038 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 defproxy.mode = PR_MODE_TCP;
1040 defproxy.state = PR_STNEW;
1041 defproxy.maxconn = cfg_maxpconn;
1042 defproxy.conn_retries = CONN_RETRIES;
1043 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001044
1045 defproxy.defsrv.inter = DEF_CHKINTR;
1046 defproxy.defsrv.fastinter = 0;
1047 defproxy.defsrv.downinter = 0;
1048 defproxy.defsrv.rise = DEF_RISETIME;
1049 defproxy.defsrv.fall = DEF_FALLTIME;
1050 defproxy.defsrv.check_port = 0;
1051 defproxy.defsrv.maxqueue = 0;
1052 defproxy.defsrv.minconn = 0;
1053 defproxy.defsrv.maxconn = 0;
1054 defproxy.defsrv.slowstart = 0;
1055 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1056 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1057 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058}
1059
Willy Tarreauade5ec42010-01-28 19:33:49 +01001060
1061static int create_cond_regex_rule(const char *file, int line,
1062 struct proxy *px, int dir, int action, int flags,
1063 const char *cmd, const char *reg, const char *repl,
1064 const char **cond_start)
1065{
1066 regex_t *preg = NULL;
1067 const char *err;
1068 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001069 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001070
1071 if (px == &defproxy) {
1072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto err;
1075 }
1076
1077 if (*reg == 0) {
1078 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1079 err_code |= ERR_ALERT | ERR_FATAL;
1080 goto err;
1081 }
1082
1083 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1084 err_code |= ERR_WARN;
1085
Willy Tarreau5321c422010-01-28 20:35:13 +01001086 if (cond_start &&
1087 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1088 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1089 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1090 file, line, cmd);
1091 err_code |= ERR_ALERT | ERR_FATAL;
1092 goto err;
1093 }
1094 }
1095 else if (cond_start && **cond_start) {
1096 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1097 file, line, cmd, *cond_start);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto err;
1100 }
1101
1102 if (dir == ACL_DIR_REQ)
1103 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001104 else
1105 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001106
Willy Tarreauade5ec42010-01-28 19:33:49 +01001107 preg = calloc(1, sizeof(regex_t));
1108 if (!preg) {
1109 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1110 err_code = ERR_ALERT | ERR_FATAL;
1111 goto err;
1112 }
1113
1114 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1115 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1116 err_code = ERR_ALERT | ERR_FATAL;
1117 goto err;
1118 }
1119
1120 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001121 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001122 if (repl && err) {
1123 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1124 file, line, cmd, *err);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto err;
1127 }
1128
1129 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1130 err_code |= ERR_WARN;
1131
1132 return err_code;
1133 err:
1134 free(preg);
1135 return err_code;
1136}
1137
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001139 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001140 * Returns the error code, 0 if OK, or any combination of :
1141 * - ERR_ABORT: must abort ASAP
1142 * - ERR_FATAL: we can continue parsing but not start the service
1143 * - ERR_WARN: a warning has been emitted
1144 * - ERR_ALERT: an alert has been emitted
1145 * Only the two first ones can stop processing, the two others are just
1146 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001148int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1149{
1150 static struct peers *curpeers = NULL;
1151 struct peer *newpeer = NULL;
1152 const char *err;
1153 int err_code = 0;
1154
1155 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1156
1157 err = invalid_char(args[1]);
1158 if (err) {
1159 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1160 file, linenum, *err, args[0], args[1]);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 }
1163
1164 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1165 /*
1166 * If there are two proxies with the same name only following
1167 * combinations are allowed:
1168 */
1169 if (strcmp(curpeers->id, args[1]) == 0) {
1170 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1171 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1172 err_code |= ERR_WARN;
1173 }
1174 }
1175
1176 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1177 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1178 err_code |= ERR_ALERT | ERR_ABORT;
1179 goto out;
1180 }
1181
1182 curpeers->next = peers;
1183 peers = curpeers;
1184 curpeers->conf.file = file;
1185 curpeers->conf.line = linenum;
1186 curpeers->last_change = now.tv_sec;
1187 curpeers->id = strdup(args[1]);
1188 }
1189 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1190 char *rport, *raddr;
1191 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001192 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001193
1194 if (!*args[2]) {
1195 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1196 file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200
1201 err = invalid_char(args[1]);
1202 if (err) {
1203 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1204 file, linenum, *err, args[1]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208
1209 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1210 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1211 err_code |= ERR_ALERT | ERR_ABORT;
1212 goto out;
1213 }
1214
1215 /* the peers are linked backwards first */
1216 curpeers->count++;
1217 newpeer->next = curpeers->remote;
1218 curpeers->remote = newpeer;
1219 newpeer->peers = curpeers;
1220 newpeer->conf.file = file;
1221 newpeer->conf.line = linenum;
1222
1223 newpeer->last_change = now.tv_sec;
1224 newpeer->id = strdup(args[1]);
1225
1226 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001227 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001228 if (rport) {
1229 *rport++ = 0;
1230 realport = atol(rport);
1231 }
1232 if (!realport) {
1233 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1234 err_code |= ERR_ALERT | ERR_FATAL;
1235 goto out;
1236 }
1237
Willy Tarreaufab5a432011-03-04 15:31:53 +01001238 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001239 free(raddr);
1240 if (!sk) {
1241 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001246 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001247
1248 if (strcmp(newpeer->id, localpeer) == 0) {
1249 /* Current is local peer, it define a frontend */
1250 newpeer->local = 1;
1251
1252 if (!curpeers->peers_fe) {
1253 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1254 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1255 err_code |= ERR_ALERT | ERR_ABORT;
1256 goto out;
1257 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001258
Willy Tarreau237250c2011-07-29 01:49:03 +02001259 init_new_proxy(curpeers->peers_fe);
1260 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001261
1262 curpeers->peers_fe->last_change = now.tv_sec;
1263 curpeers->peers_fe->id = strdup(args[1]);
1264 curpeers->peers_fe->cap = PR_CAP_FE;
1265 curpeers->peers_fe->maxconn = 65000;
1266 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1267 curpeers->peers_fe->timeout.connect = 5000;
1268 curpeers->peers_fe->accept = peer_accept;
1269 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001270 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001271 err_code |= ERR_FATAL;
1272 goto out;
1273 }
1274 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1275 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1276 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1277 curpeers->peers_fe->listen->accept = session_accept;
1278 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1279 curpeers->peers_fe->listen->handler = process_session;
1280 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1281 }
1282 }
1283 } /* neither "peer" nor "peers" */
1284 else if (*args[0] != 0) {
1285 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289
1290out:
1291 return err_code;
1292}
1293
1294
Willy Tarreau3842f002009-06-14 11:39:52 +02001295int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001296{
1297 static struct proxy *curproxy = NULL;
1298 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001299 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001300 int rc;
1301 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001302 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001303 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304
Willy Tarreau977b8e42006-12-29 14:19:17 +01001305 if (!strcmp(args[0], "listen"))
1306 rc = PR_CAP_LISTEN;
1307 else if (!strcmp(args[0], "frontend"))
1308 rc = PR_CAP_FE | PR_CAP_RS;
1309 else if (!strcmp(args[0], "backend"))
1310 rc = PR_CAP_BE | PR_CAP_RS;
1311 else if (!strcmp(args[0], "ruleset"))
1312 rc = PR_CAP_RS;
1313 else
1314 rc = PR_CAP_NONE;
1315
1316 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317 if (!*args[1]) {
1318 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1319 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1320 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001321 err_code |= ERR_ALERT | ERR_ABORT;
1322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001324
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001325 err = invalid_char(args[1]);
1326 if (err) {
1327 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1328 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001329 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001330 }
1331
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001332 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1333 /*
1334 * If there are two proxies with the same name only following
1335 * combinations are allowed:
1336 *
1337 * listen backend frontend ruleset
1338 * listen - - - -
1339 * backend - - OK -
1340 * frontend - OK - -
1341 * ruleset - - - -
1342 */
1343
1344 if (!strcmp(curproxy->id, args[1]) &&
1345 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1346 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001347 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1348 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1349 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001350 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001351 }
1352 }
1353
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001356 err_code |= ERR_ALERT | ERR_ABORT;
1357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001359
Willy Tarreau97cb7802010-01-03 20:23:58 +01001360 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 curproxy->next = proxy;
1362 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001363 curproxy->conf.file = file;
1364 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001365 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001367 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368
1369 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001370 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001371 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001372 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001373 err_code |= ERR_FATAL;
1374 goto out;
1375 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001376 new = curproxy->listen;
1377 while (new != last) {
1378 new->conf.file = file;
1379 new->conf.line = linenum;
1380 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001381 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001382 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384
1385 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001386 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001387 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001388
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001391 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001392 curproxy->no_options = defproxy.no_options;
1393 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001394 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001395 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001396 curproxy->except_net = defproxy.except_net;
1397 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001398 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001399 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001401 if (defproxy.fwdfor_hdr_len) {
1402 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1403 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1404 }
1405
Willy Tarreaub86db342009-11-30 11:50:16 +01001406 if (defproxy.orgto_hdr_len) {
1407 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1408 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1409 }
1410
Willy Tarreau977b8e42006-12-29 14:19:17 +01001411 if (curproxy->cap & PR_CAP_FE) {
1412 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001413 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001414 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001415
1416 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001417 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1418 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001419
1420 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422
Willy Tarreau977b8e42006-12-29 14:19:17 +01001423 if (curproxy->cap & PR_CAP_BE) {
1424 curproxy->fullconn = defproxy.fullconn;
1425 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001427 if (defproxy.check_req) {
1428 curproxy->check_req = calloc(1, defproxy.check_len);
1429 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1430 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001431 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001433 if (defproxy.expect_str) {
1434 curproxy->expect_str = strdup(defproxy.expect_str);
1435 if (defproxy.expect_regex) {
1436 /* note: this regex is known to be valid */
1437 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1438 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1439 }
1440 }
1441
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442 if (defproxy.cookie_name)
1443 curproxy->cookie_name = strdup(defproxy.cookie_name);
1444 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001445 if (defproxy.cookie_domain)
1446 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001447
Willy Tarreau31936852010-10-06 16:59:56 +02001448 if (defproxy.cookie_maxidle)
1449 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1450
1451 if (defproxy.cookie_maxlife)
1452 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1453
Emeric Brun647caf12009-06-30 17:57:00 +02001454 if (defproxy.rdp_cookie_name)
1455 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1456 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1457
Willy Tarreau01732802007-11-01 22:48:15 +01001458 if (defproxy.url_param_name)
1459 curproxy->url_param_name = strdup(defproxy.url_param_name);
1460 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001461
Benoitaffb4812009-03-25 13:02:10 +01001462 if (defproxy.hh_name)
1463 curproxy->hh_name = strdup(defproxy.hh_name);
1464 curproxy->hh_len = defproxy.hh_len;
1465 curproxy->hh_match_domain = defproxy.hh_match_domain;
1466
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001467 if (defproxy.iface_name)
1468 curproxy->iface_name = strdup(defproxy.iface_name);
1469 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001472 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 if (defproxy.capture_name)
1474 curproxy->capture_name = strdup(defproxy.capture_name);
1475 curproxy->capture_namelen = defproxy.capture_namelen;
1476 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001480 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001481 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001482 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001483 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001484 curproxy->uri_auth = defproxy.uri_auth;
1485 curproxy->mon_net = defproxy.mon_net;
1486 curproxy->mon_mask = defproxy.mon_mask;
1487 if (defproxy.monitor_uri)
1488 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1489 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001490 if (defproxy.defbe.name)
1491 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001492 }
1493
1494 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001495 curproxy->timeout.connect = defproxy.timeout.connect;
1496 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001497 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001498 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001499 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001500 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001501 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 curproxy->source_addr = defproxy.source_addr;
1503 }
1504
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 curproxy->mode = defproxy.mode;
1506 curproxy->logfac1 = defproxy.logfac1;
1507 curproxy->logsrv1 = defproxy.logsrv1;
1508 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001509 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 curproxy->logfac2 = defproxy.logfac2;
1511 curproxy->logsrv2 = defproxy.logsrv2;
1512 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001513 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001515 curproxy->conf.used_listener_id = EB_ROOT;
1516 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001517
Willy Tarreau93893792009-07-23 13:19:11 +02001518 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 }
1520 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1521 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001522 /* FIXME-20070101: we should do this too at the end of the
1523 * config parsing to free all default values.
1524 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001525 free(defproxy.check_req);
1526 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001527 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001528 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001529 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001530 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001531 free(defproxy.capture_name);
1532 free(defproxy.monitor_uri);
1533 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001534 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001535 free(defproxy.fwdfor_hdr_name);
1536 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001537 free(defproxy.orgto_hdr_name);
1538 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001539 free(defproxy.expect_str);
1540 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001541
Willy Tarreaua534fea2008-08-03 12:19:50 +02001542 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001543 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001544
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 /* we cannot free uri_auth because it might already be used */
1546 init_default_instance();
1547 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001548 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 }
1551 else if (curproxy == NULL) {
1552 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 }
1556
Willy Tarreau977b8e42006-12-29 14:19:17 +01001557
1558 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001560 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001561 int cur_arg;
1562
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 if (curproxy == &defproxy) {
1564 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001565 err_code |= ERR_ALERT | ERR_FATAL;
1566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001568 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001569 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570
Emeric Bruned760922010-10-22 17:59:25 +02001571 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001572 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001574 err_code |= ERR_ALERT | ERR_FATAL;
1575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001577
1578 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001579
1580 /* NOTE: the following line might create several listeners if there
1581 * are comma-separated IPs or port ranges. So all further processing
1582 * will have to be applied to all listeners created after last_listen.
1583 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001584 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
1586 goto out;
1587 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001588
Willy Tarreau90a570f2009-10-04 20:54:54 +02001589 new_listen = curproxy->listen;
1590 while (new_listen != last_listen) {
1591 new_listen->conf.file = file;
1592 new_listen->conf.line = linenum;
1593 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001594 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001595 }
1596
Emeric Bruned760922010-10-22 17:59:25 +02001597 /* Set default global rights and owner for unix bind */
1598 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1599 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1600 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001601 cur_arg = 2;
1602 while (*(args[cur_arg])) {
1603 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1604#ifdef SO_BINDTODEVICE
1605 struct listener *l;
1606
Emeric Bruned760922010-10-22 17:59:25 +02001607 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1608 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1609 file, linenum, args[0], args[cur_arg]);
1610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
1612 }
1613
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001614 if (!*args[cur_arg + 1]) {
1615 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1616 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001617 err_code |= ERR_ALERT | ERR_FATAL;
1618 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001619 }
1620
1621 for (l = curproxy->listen; l != last_listen; l = l->next)
1622 l->interface = strdup(args[cur_arg + 1]);
1623
1624 global.last_checks |= LSTCHK_NETADM;
1625
1626 cur_arg += 2;
1627 continue;
1628#else
1629 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1630 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001633#endif
1634 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001635 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1636#ifdef TCP_MAXSEG
1637 struct listener *l;
1638 int mss;
1639
Emeric Bruned760922010-10-22 17:59:25 +02001640 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1641 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1642 file, linenum, args[0], args[cur_arg]);
1643 err_code |= ERR_ALERT | ERR_FATAL;
1644 goto out;
1645 }
1646
Willy Tarreaube1b9182009-06-14 18:48:19 +02001647 if (!*args[cur_arg + 1]) {
1648 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1649 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001652 }
1653
Willy Tarreau48a7e722010-12-24 15:26:39 +01001654 mss = atoi(args[cur_arg + 1]);
1655 if (!mss || abs(mss) > 65535) {
1656 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001660 }
1661
1662 for (l = curproxy->listen; l != last_listen; l = l->next)
1663 l->maxseg = mss;
1664
1665 cur_arg += 2;
1666 continue;
1667#else
1668 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1669 file, linenum, args[0], args[cur_arg]);
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#endif
1673 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001674
1675 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1676#ifdef TCP_DEFER_ACCEPT
1677 struct listener *l;
1678
1679 for (l = curproxy->listen; l != last_listen; l = l->next)
1680 l->options |= LI_O_DEF_ACCEPT;
1681
1682 cur_arg ++;
1683 continue;
1684#else
1685 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1686 file, linenum, args[0], args[cur_arg]);
1687 err_code |= ERR_ALERT | ERR_FATAL;
1688 goto out;
1689#endif
1690 }
1691
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001692 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001693#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001694 struct listener *l;
1695
Emeric Bruned760922010-10-22 17:59:25 +02001696 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1697 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1698 file, linenum, args[0], args[cur_arg]);
1699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
1701 }
1702
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001705
1706 cur_arg ++;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001714 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001715
Willy Tarreau8a956912010-10-15 14:27:08 +02001716 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1717 struct listener *l;
1718
1719 for (l = curproxy->listen; l != last_listen; l = l->next)
1720 l->options |= LI_O_ACC_PROXY;
1721
1722 cur_arg ++;
1723 continue;
1724 }
1725
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001726 if (!strcmp(args[cur_arg], "name")) {
1727 struct listener *l;
1728
1729 for (l = curproxy->listen; l != last_listen; l = l->next)
1730 l->name = strdup(args[cur_arg + 1]);
1731
1732 cur_arg += 2;
1733 continue;
1734 }
1735
1736 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001737 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001738 struct listener *l;
1739
1740 if (curproxy->listen->next != last_listen) {
1741 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1742 file, linenum, args[cur_arg]);
1743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
1745 }
1746
1747 if (!*args[cur_arg + 1]) {
1748 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1749 file, linenum, args[cur_arg]);
1750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
1752 }
1753
1754 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001755 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001756
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001757 if (curproxy->listen->luid <= 0) {
1758 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001759 file, linenum);
1760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
1762 }
1763
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001764 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1765 if (node) {
1766 l = container_of(node, struct listener, conf.id);
1767 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1768 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1773
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001774 cur_arg += 2;
1775 continue;
1776 }
1777
Emeric Bruned760922010-10-22 17:59:25 +02001778 if (!strcmp(args[cur_arg], "mode")) {
1779
1780 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1781 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1782 file, linenum, args[0], args[cur_arg]);
1783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
1785 }
1786
1787 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1788
1789 cur_arg += 2;
1790 continue;
1791 }
1792
1793 if (!strcmp(args[cur_arg], "uid")) {
1794
1795 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1796 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1797 file, linenum, args[0], args[cur_arg]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801
1802 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1803 cur_arg += 2;
1804 continue;
1805 }
1806
1807 if (!strcmp(args[cur_arg], "gid")) {
1808
1809 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1810 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1811 file, linenum, args[0], args[cur_arg]);
1812 err_code |= ERR_ALERT | ERR_FATAL;
1813 goto out;
1814 }
1815
1816 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1817 cur_arg += 2;
1818 continue;
1819 }
1820
1821 if (!strcmp(args[cur_arg], "user")) {
1822 struct passwd *user;
1823
1824 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1825 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1826 file, linenum, args[0], args[cur_arg]);
1827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
1830 user = getpwnam(args[cur_arg + 1]);
1831 if (!user) {
1832 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1833 file, linenum, args[0], args[cur_arg + 1 ]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
1838 curproxy->listen->perm.ux.uid = user->pw_uid;
1839 cur_arg += 2;
1840 continue;
1841 }
1842
1843 if (!strcmp(args[cur_arg], "group")) {
1844 struct group *group;
1845
1846 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1847 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1848 file, linenum, args[0], args[cur_arg]);
1849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 }
1852 group = getgrnam(args[cur_arg + 1]);
1853 if (!group) {
1854 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1855 file, linenum, args[0], args[cur_arg + 1 ]);
1856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
1858 }
1859
1860 curproxy->listen->perm.ux.gid = group->gr_gid;
1861 cur_arg += 2;
1862 continue;
1863 }
1864
Willy Tarreaub48f9582011-09-05 01:17:06 +02001865 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001866 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001869 }
Willy Tarreau93893792009-07-23 13:19:11 +02001870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001871 }
1872 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1873 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1874 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001876 err_code |= ERR_ALERT | ERR_FATAL;
1877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001878 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001879 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882 /* flush useless bits */
1883 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001885 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001886 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889
Willy Tarreau1c47f852006-07-09 08:22:27 +02001890 if (!*args[1]) {
1891 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001895 }
1896
Willy Tarreaua534fea2008-08-03 12:19:50 +02001897 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001898 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001899 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001900 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001901 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1902
Willy Tarreau93893792009-07-23 13:19:11 +02001903 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1906 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1907 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1908 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1909 else {
1910 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 }
1914 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001915 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001916 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001917
1918 if (curproxy == &defproxy) {
1919 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001923 }
1924
1925 if (!*args[1]) {
1926 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001930 }
1931
1932 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001933 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001934
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001935 if (curproxy->uuid <= 0) {
1936 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001937 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001940 }
1941
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001942 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1943 if (node) {
1944 struct proxy *target = container_of(node, struct proxy, conf.id);
1945 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1946 file, linenum, proxy_type_str(curproxy), curproxy->id,
1947 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
1950 }
1951 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001952 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001953 else if (!strcmp(args[0], "description")) {
1954 int i, len=0;
1955 char *d;
1956
Cyril Bonté99ed3272010-01-24 23:29:44 +01001957 if (curproxy == &defproxy) {
1958 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1959 file, linenum, args[0]);
1960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
1962 }
1963
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001964 if (!*args[1]) {
1965 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1966 file, linenum, args[0]);
1967 return -1;
1968 }
1969
1970 for(i=1; *args[i]; i++)
1971 len += strlen(args[i])+1;
1972
1973 d = (char *)calloc(1, len);
1974 curproxy->desc = d;
1975
1976 d += sprintf(d, "%s", args[1]);
1977 for(i=2; *args[i]; i++)
1978 d += sprintf(d, " %s", args[i]);
1979
1980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1982 curproxy->state = PR_STSTOPPED;
1983 }
1984 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1985 curproxy->state = PR_STNEW;
1986 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001987 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1988 int cur_arg = 1;
1989 unsigned int set = 0;
1990
1991 while (*args[cur_arg]) {
1992 int u;
1993 if (strcmp(args[cur_arg], "all") == 0) {
1994 set = 0;
1995 break;
1996 }
1997 else if (strcmp(args[cur_arg], "odd") == 0) {
1998 set |= 0x55555555;
1999 }
2000 else if (strcmp(args[cur_arg], "even") == 0) {
2001 set |= 0xAAAAAAAA;
2002 }
2003 else {
2004 u = str2uic(args[cur_arg]);
2005 if (u < 1 || u > 32) {
2006 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002010 }
2011 if (u > global.nbproc) {
2012 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002014 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002015 }
2016 set |= 1 << (u - 1);
2017 }
2018 cur_arg++;
2019 }
2020 curproxy->bind_proc = set;
2021 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002022 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002023 if (curproxy == &defproxy) {
2024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002025 err_code |= ERR_ALERT | ERR_FATAL;
2026 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002027 }
2028
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002029 err = invalid_char(args[1]);
2030 if (err) {
2031 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2032 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002034 }
2035
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002036 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2037 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2038 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002041 }
2042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002043 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2044 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 if (*(args[1]) == 0) {
2050 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2051 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002055
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002056 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002057 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002058 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002059 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002060 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 curproxy->cookie_name = strdup(args[1]);
2062 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002063
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 cur_arg = 2;
2065 while (*(args[cur_arg])) {
2066 if (!strcmp(args[cur_arg], "rewrite")) {
2067 curproxy->options |= PR_O_COOK_RW;
2068 }
2069 else if (!strcmp(args[cur_arg], "indirect")) {
2070 curproxy->options |= PR_O_COOK_IND;
2071 }
2072 else if (!strcmp(args[cur_arg], "insert")) {
2073 curproxy->options |= PR_O_COOK_INS;
2074 }
2075 else if (!strcmp(args[cur_arg], "nocache")) {
2076 curproxy->options |= PR_O_COOK_NOC;
2077 }
2078 else if (!strcmp(args[cur_arg], "postonly")) {
2079 curproxy->options |= PR_O_COOK_POST;
2080 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002081 else if (!strcmp(args[cur_arg], "preserve")) {
2082 curproxy->options2 |= PR_O2_COOK_PSV;
2083 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 else if (!strcmp(args[cur_arg], "prefix")) {
2085 curproxy->options |= PR_O_COOK_PFX;
2086 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002087 else if (!strcmp(args[cur_arg], "domain")) {
2088 if (!*args[cur_arg + 1]) {
2089 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2090 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002091 err_code |= ERR_ALERT | ERR_FATAL;
2092 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002093 }
2094
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002095 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002096 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002097 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2098 " dots nor does not start with a dot."
2099 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002100 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002101 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002102 }
2103
2104 err = invalid_domainchar(args[cur_arg + 1]);
2105 if (err) {
2106 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2107 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_ALERT | ERR_FATAL;
2109 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002110 }
2111
Willy Tarreau68a897b2009-12-03 23:28:34 +01002112 if (!curproxy->cookie_domain) {
2113 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2114 } else {
2115 /* one domain was already specified, add another one by
2116 * building the string which will be returned along with
2117 * the cookie.
2118 */
2119 char *new_ptr;
2120 int new_len = strlen(curproxy->cookie_domain) +
2121 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2122 new_ptr = malloc(new_len);
2123 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2124 free(curproxy->cookie_domain);
2125 curproxy->cookie_domain = new_ptr;
2126 }
Willy Tarreau31936852010-10-06 16:59:56 +02002127 cur_arg++;
2128 }
2129 else if (!strcmp(args[cur_arg], "maxidle")) {
2130 unsigned int maxidle;
2131 const char *res;
2132
2133 if (!*args[cur_arg + 1]) {
2134 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2135 file, linenum, args[cur_arg]);
2136 err_code |= ERR_ALERT | ERR_FATAL;
2137 goto out;
2138 }
2139
2140 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2141 if (res) {
2142 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2143 file, linenum, *res, args[cur_arg]);
2144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
2146 }
2147 curproxy->cookie_maxidle = maxidle;
2148 cur_arg++;
2149 }
2150 else if (!strcmp(args[cur_arg], "maxlife")) {
2151 unsigned int maxlife;
2152 const char *res;
2153
2154 if (!*args[cur_arg + 1]) {
2155 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2156 file, linenum, args[cur_arg]);
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
2161 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2162 if (res) {
2163 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2164 file, linenum, *res, args[cur_arg]);
2165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
2167 }
2168 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002169 cur_arg++;
2170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002172 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 +02002173 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
2177 cur_arg++;
2178 }
2179 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2180 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2181 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }
2184
2185 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2186 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2187 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002190
2191 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2192 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2193 file, linenum);
2194 err_code |= ERR_ALERT | ERR_FATAL;
2195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002197 else if (!strcmp(args[0], "persist")) { /* persist */
2198 if (*(args[1]) == 0) {
2199 Alert("parsing [%s:%d] : missing persist method.\n",
2200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
2202 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002203 }
2204
2205 if (!strncmp(args[1], "rdp-cookie", 10)) {
2206 curproxy->options2 |= PR_O2_RDPC_PRST;
2207
Emeric Brunb982a3d2010-01-04 15:45:53 +01002208 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002209 const char *beg, *end;
2210
2211 beg = args[1] + 11;
2212 end = strchr(beg, ')');
2213
2214 if (!end || end == beg) {
2215 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2216 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002217 err_code |= ERR_ALERT | ERR_FATAL;
2218 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002219 }
2220
2221 free(curproxy->rdp_cookie_name);
2222 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2223 curproxy->rdp_cookie_len = end-beg;
2224 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002225 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002226 free(curproxy->rdp_cookie_name);
2227 curproxy->rdp_cookie_name = strdup("msts");
2228 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2229 }
2230 else { /* syntax */
2231 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2232 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002235 }
2236 }
2237 else {
2238 Alert("parsing [%s:%d] : unknown persist method.\n",
2239 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002240 err_code |= ERR_ALERT | ERR_FATAL;
2241 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002242 }
2243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002244 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002245 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002246
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002247 if (curproxy == &defproxy) {
2248 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252
Willy Tarreau977b8e42006-12-29 14:19:17 +01002253 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002257 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
2262 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002263 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 curproxy->appsession_name = strdup(args[1]);
2265 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2266 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002267 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2268 if (err) {
2269 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2270 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002273 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002274 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002275
Willy Tarreau51041c72007-09-09 21:56:53 +02002276 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2277 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_ABORT;
2279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002281
2282 cur_arg = 6;
2283 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002284 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2285 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002286 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002287 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002288 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002289 } else if (!strcmp(args[cur_arg], "prefix")) {
2290 curproxy->options2 |= PR_O2_AS_PFX;
2291 } else if (!strcmp(args[cur_arg], "mode")) {
2292 if (!*args[cur_arg + 1]) {
2293 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2294 file, linenum, args[0], args[cur_arg]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298
2299 cur_arg++;
2300 if (!strcmp(args[cur_arg], "query-string")) {
2301 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2302 curproxy->options2 |= PR_O2_AS_M_QS;
2303 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2304 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2305 curproxy->options2 |= PR_O2_AS_M_PP;
2306 } else {
2307 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2308 err_code |= ERR_ALERT | ERR_FATAL;
2309 goto out;
2310 }
2311 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002312 cur_arg++;
2313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 } /* Url App Session */
2315 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002316 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002318
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002320 if (curproxy == &defproxy) {
2321 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 if (*(args[4]) == 0) {
2327 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2328 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002332 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 curproxy->capture_name = strdup(args[2]);
2334 curproxy->capture_namelen = strlen(curproxy->capture_name);
2335 curproxy->capture_len = atol(args[4]);
2336 if (curproxy->capture_len >= CAPTURE_LEN) {
2337 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2338 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 curproxy->capture_len = CAPTURE_LEN - 1;
2341 }
2342 curproxy->to_log |= LW_COOKIE;
2343 }
2344 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2345 struct cap_hdr *hdr;
2346
2347 if (curproxy == &defproxy) {
2348 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 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 }
2352
2353 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2354 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2355 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 }
2359
2360 hdr = calloc(sizeof(struct cap_hdr), 1);
2361 hdr->next = curproxy->req_cap;
2362 hdr->name = strdup(args[3]);
2363 hdr->namelen = strlen(args[3]);
2364 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002365 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 hdr->index = curproxy->nb_req_cap++;
2367 curproxy->req_cap = hdr;
2368 curproxy->to_log |= LW_REQHDR;
2369 }
2370 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2371 struct cap_hdr *hdr;
2372
2373 if (curproxy == &defproxy) {
2374 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 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
2378
2379 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2380 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2381 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
2385 hdr = calloc(sizeof(struct cap_hdr), 1);
2386 hdr->next = curproxy->rsp_cap;
2387 hdr->name = strdup(args[3]);
2388 hdr->namelen = strlen(args[3]);
2389 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002390 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 hdr->index = curproxy->nb_rsp_cap++;
2392 curproxy->rsp_cap = hdr;
2393 curproxy->to_log |= LW_RSPHDR;
2394 }
2395 else {
2396 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 }
2401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002403 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002405
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 if (*(args[1]) == 0) {
2407 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2408 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 curproxy->conn_retries = atol(args[1]);
2413 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002414 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002415 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002416
2417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
2421 }
2422
Willy Tarreauff011f22011-01-06 17:51:27 +01002423 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 +01002424 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2425 file, linenum, args[0]);
2426 err_code |= ERR_WARN;
2427 }
2428
Willy Tarreauff011f22011-01-06 17:51:27 +01002429 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002430
Willy Tarreauff011f22011-01-06 17:51:27 +01002431 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002432 err_code |= ERR_ALERT | ERR_ABORT;
2433 goto out;
2434 }
2435
Willy Tarreauff011f22011-01-06 17:51:27 +01002436 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2437 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002438 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002439 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002440 if (curproxy == &defproxy) {
2441 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002442 err_code |= ERR_ALERT | ERR_FATAL;
2443 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002444 }
2445
Willy Tarreauef6494c2010-01-28 17:12:36 +01002446 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002447 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002451 }
2452
Willy Tarreauef6494c2010-01-28 17:12:36 +01002453 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002454 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2455 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002458 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002459
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002460 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002461 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002462 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002463 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002464 struct redirect_rule *rule;
2465 int cur_arg;
2466 int type = REDIRECT_TYPE_NONE;
2467 int code = 302;
2468 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002469 char *cookie = NULL;
2470 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002471 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002472
Cyril Bonté99ed3272010-01-24 23:29:44 +01002473 if (curproxy == &defproxy) {
2474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
2477 }
2478
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002479 cur_arg = 1;
2480 while (*(args[cur_arg])) {
2481 if (!strcmp(args[cur_arg], "location")) {
2482 if (!*args[cur_arg + 1]) {
2483 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2484 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002487 }
2488
2489 type = REDIRECT_TYPE_LOCATION;
2490 cur_arg++;
2491 destination = args[cur_arg];
2492 }
2493 else if (!strcmp(args[cur_arg], "prefix")) {
2494 if (!*args[cur_arg + 1]) {
2495 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2496 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002499 }
2500
2501 type = REDIRECT_TYPE_PREFIX;
2502 cur_arg++;
2503 destination = args[cur_arg];
2504 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002505 else if (!strcmp(args[cur_arg], "set-cookie")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002511 }
2512
2513 cur_arg++;
2514 cookie = args[cur_arg];
2515 cookie_set = 1;
2516 }
2517 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2518 if (!*args[cur_arg + 1]) {
2519 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2520 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002523 }
2524
2525 cur_arg++;
2526 cookie = args[cur_arg];
2527 cookie_set = 0;
2528 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002529 else if (!strcmp(args[cur_arg],"code")) {
2530 if (!*args[cur_arg + 1]) {
2531 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2532 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002535 }
2536 cur_arg++;
2537 code = atol(args[cur_arg]);
2538 if (code < 301 || code > 303) {
2539 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2540 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002543 }
2544 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002545 else if (!strcmp(args[cur_arg],"drop-query")) {
2546 flags |= REDIRECT_FLAG_DROP_QS;
2547 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002548 else if (!strcmp(args[cur_arg],"append-slash")) {
2549 flags |= REDIRECT_FLAG_APPEND_SLASH;
2550 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002551 else if (strcmp(args[cur_arg], "if") == 0 ||
2552 strcmp(args[cur_arg], "unless") == 0) {
2553 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2554 if (!cond) {
2555 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2556 file, linenum, args[0]);
2557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
2559 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002560 break;
2561 }
2562 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002563 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 +02002564 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002567 }
2568 cur_arg++;
2569 }
2570
2571 if (type == REDIRECT_TYPE_NONE) {
2572 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2573 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002576 }
2577
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2579 rule->cond = cond;
2580 rule->rdr_str = strdup(destination);
2581 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002582 if (cookie) {
2583 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002584 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002585 */
2586 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002587 if (cookie_set) {
2588 rule->cookie_str = malloc(rule->cookie_len + 10);
2589 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2590 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2591 rule->cookie_len += 9;
2592 } else {
2593 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002594 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002595 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2596 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002597 }
2598 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002599 rule->type = type;
2600 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002601 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002602 LIST_INIT(&rule->list);
2603 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002604 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2605 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002606 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002607 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002608 struct switching_rule *rule;
2609
Willy Tarreaub099aca2008-10-12 17:26:37 +02002610 if (curproxy == &defproxy) {
2611 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002614 }
2615
Willy Tarreau55ea7572007-06-17 19:56:27 +02002616 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618
2619 if (*(args[1]) == 0) {
2620 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002623 }
2624
Willy Tarreauef6494c2010-01-28 17:12:36 +01002625 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002626 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2627 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002630 }
2631
Willy Tarreauef6494c2010-01-28 17:12:36 +01002632 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002633 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002634 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002637 }
2638
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002639 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002640
Willy Tarreau55ea7572007-06-17 19:56:27 +02002641 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2642 rule->cond = cond;
2643 rule->be.name = strdup(args[1]);
2644 LIST_INIT(&rule->list);
2645 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2646 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002647 else if ((!strcmp(args[0], "force-persist")) ||
2648 (!strcmp(args[0], "ignore-persist"))) {
2649 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002650
2651 if (curproxy == &defproxy) {
2652 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656
2657 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2658 err_code |= ERR_WARN;
2659
Willy Tarreauef6494c2010-01-28 17:12:36 +01002660 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002661 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2662 file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
Willy Tarreauef6494c2010-01-28 17:12:36 +01002667 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002668 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2669 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
2672 }
2673
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002674 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002675
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002676 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002677 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002678 if (!strcmp(args[0], "force-persist")) {
2679 rule->type = PERSIST_TYPE_FORCE;
2680 } else {
2681 rule->type = PERSIST_TYPE_IGNORE;
2682 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002683 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002684 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002685 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002686 else if (!strcmp(args[0], "stick-table")) {
2687 int myidx = 1;
2688
Emeric Brun32da3c42010-09-23 18:39:19 +02002689 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002690 curproxy->table.type = (unsigned int)-1;
2691 while (*args[myidx]) {
2692 const char *err;
2693
2694 if (strcmp(args[myidx], "size") == 0) {
2695 myidx++;
2696 if (!*(args[myidx])) {
2697 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2698 file, linenum, args[myidx-1]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2703 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2704 file, linenum, *err, args[myidx-1]);
2705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
2707 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002708 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002709 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002710 else if (strcmp(args[myidx], "peers") == 0) {
2711 myidx++;
2712 if (!*(args[myidx])) {
2713 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2714 file, linenum, args[myidx-1]);
2715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
2717 }
2718 curproxy->table.peers.name = strdup(args[myidx++]);
2719 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002720 else if (strcmp(args[myidx], "expire") == 0) {
2721 myidx++;
2722 if (!*(args[myidx])) {
2723 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2724 file, linenum, args[myidx-1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2729 if (err) {
2730 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2731 file, linenum, *err, args[myidx-1]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002736 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002737 }
2738 else if (strcmp(args[myidx], "nopurge") == 0) {
2739 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002740 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002741 }
2742 else if (strcmp(args[myidx], "type") == 0) {
2743 myidx++;
2744 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2745 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2746 file, linenum, args[myidx]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002750 /* myidx already points to next arg */
2751 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002752 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002753 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002754 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002755
2756 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002757 nw = args[myidx];
2758 while (*nw) {
2759 /* the "store" keyword supports a comma-separated list */
2760 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002761 sa = NULL; /* store arg */
2762 while (*nw && *nw != ',') {
2763 if (*nw == '(') {
2764 *nw = 0;
2765 sa = ++nw;
2766 while (*nw != ')') {
2767 if (!*nw) {
2768 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2769 file, linenum, args[0], cw);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
2773 nw++;
2774 }
2775 *nw = '\0';
2776 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002777 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002778 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002779 if (*nw)
2780 *nw++ = '\0';
2781 type = stktable_get_data_type(cw);
2782 if (type < 0) {
2783 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2784 file, linenum, args[0], cw);
2785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
2787 }
Willy Tarreauac782882010-06-20 10:41:54 +02002788
2789 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2790 switch (err) {
2791 case PE_NONE: break;
2792 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002793 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2794 file, linenum, args[0], cw);
2795 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002796 break;
2797
2798 case PE_ARG_MISSING:
2799 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2800 file, linenum, args[0], cw);
2801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
2803
2804 case PE_ARG_NOT_USED:
2805 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2806 file, linenum, args[0], cw);
2807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
2809
2810 default:
2811 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2812 file, linenum, args[0], cw);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002815 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002816 }
2817 myidx++;
2818 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002819 else {
2820 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2821 file, linenum, args[myidx]);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002824 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002825 }
2826
2827 if (!curproxy->table.size) {
2828 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2829 file, linenum);
2830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
2832 }
2833
2834 if (curproxy->table.type == (unsigned int)-1) {
2835 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2836 file, linenum);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840 }
2841 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002842 struct sticking_rule *rule;
2843 struct pattern_expr *expr;
2844 int myidx = 0;
2845 const char *name = NULL;
2846 int flags;
2847
2848 if (curproxy == &defproxy) {
2849 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2855 err_code |= ERR_WARN;
2856 goto out;
2857 }
2858
2859 myidx++;
2860 if ((strcmp(args[myidx], "store") == 0) ||
2861 (strcmp(args[myidx], "store-request") == 0)) {
2862 myidx++;
2863 flags = STK_IS_STORE;
2864 }
2865 else if (strcmp(args[myidx], "store-response") == 0) {
2866 myidx++;
2867 flags = STK_IS_STORE | STK_ON_RSP;
2868 }
2869 else if (strcmp(args[myidx], "match") == 0) {
2870 myidx++;
2871 flags = STK_IS_MATCH;
2872 }
2873 else if (strcmp(args[myidx], "on") == 0) {
2874 myidx++;
2875 flags = STK_IS_MATCH | STK_IS_STORE;
2876 }
2877 else {
2878 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882
2883 if (*(args[myidx]) == 0) {
2884 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888
Emeric Brun485479d2010-09-23 18:02:19 +02002889 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002891 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
2896 if (flags & STK_ON_RSP) {
2897 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2898 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2899 file, linenum, args[0], expr->fetch->kw);
2900 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002901 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002902 goto out;
2903 }
2904 } else {
2905 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2906 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2907 file, linenum, args[0], expr->fetch->kw);
2908 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002909 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 goto out;
2911 }
2912 }
2913
2914 if (strcmp(args[myidx], "table") == 0) {
2915 myidx++;
2916 name = args[myidx++];
2917 }
2918
Willy Tarreauef6494c2010-01-28 17:12:36 +01002919 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2920 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002921 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2922 file, linenum, args[0]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002924 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002925 goto out;
2926 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002927 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 else if (*(args[myidx])) {
2929 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2930 file, linenum, args[0], args[myidx]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002932 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002933 goto out;
2934 }
Emeric Brun97679e72010-09-23 17:56:44 +02002935 if (flags & STK_ON_RSP)
2936 err_code |= warnif_cond_requires_req(cond, file, linenum);
2937 else
2938 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002939
Emeric Brunb982a3d2010-01-04 15:45:53 +01002940 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2941 rule->cond = cond;
2942 rule->expr = expr;
2943 rule->flags = flags;
2944 rule->table.name = name ? strdup(name) : NULL;
2945 LIST_INIT(&rule->list);
2946 if (flags & STK_ON_RSP)
2947 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2948 else
2949 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002953 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002954
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2956 curproxy->uri_auth = NULL; /* we must detach from the default config */
2957
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002958 if (!*args[1]) {
2959 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002960 } else if (!strcmp(args[1], "admin")) {
2961 struct stats_admin_rule *rule;
2962
2963 if (curproxy == &defproxy) {
2964 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968
2969 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2970 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2971 err_code |= ERR_ALERT | ERR_ABORT;
2972 goto out;
2973 }
2974
2975 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2976 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2977 file, linenum, args[0], args[1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2982 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2983 file, linenum, args[0], args[1]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
2988 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2989
2990 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2991 rule->cond = cond;
2992 LIST_INIT(&rule->list);
2993 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 } else if (!strcmp(args[1], "uri")) {
2995 if (*(args[2]) == 0) {
2996 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002997 err_code |= ERR_ALERT | ERR_FATAL;
2998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3000 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_ALERT | ERR_ABORT;
3002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 }
3004 } else if (!strcmp(args[1], "realm")) {
3005 if (*(args[2]) == 0) {
3006 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3010 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_ABORT;
3012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003014 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003015 unsigned interval;
3016
3017 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3018 if (err) {
3019 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3020 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003023 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_ABORT;
3026 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003027 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003028 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003029 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003030
3031 if (curproxy == &defproxy) {
3032 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036
3037 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3038 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3039 err_code |= ERR_ALERT | ERR_ABORT;
3040 goto out;
3041 }
3042
Willy Tarreauff011f22011-01-06 17:51:27 +01003043 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3044 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003045 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3046 file, linenum, args[0]);
3047 err_code |= ERR_WARN;
3048 }
3049
Willy Tarreauff011f22011-01-06 17:51:27 +01003050 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003051
Willy Tarreauff011f22011-01-06 17:51:27 +01003052 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003053 err_code |= ERR_ALERT | ERR_ABORT;
3054 goto out;
3055 }
3056
Willy Tarreauff011f22011-01-06 17:51:27 +01003057 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3058 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003059
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 } else if (!strcmp(args[1], "auth")) {
3061 if (*(args[2]) == 0) {
3062 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3066 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003067 err_code |= ERR_ALERT | ERR_ABORT;
3068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 }
3070 } else if (!strcmp(args[1], "scope")) {
3071 if (*(args[2]) == 0) {
3072 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3076 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
3080 } else if (!strcmp(args[1], "enable")) {
3081 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003086 } else if (!strcmp(args[1], "hide-version")) {
3087 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3088 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003089 err_code |= ERR_ALERT | ERR_ABORT;
3090 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003091 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003092 } else if (!strcmp(args[1], "show-legends")) {
3093 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3094 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3095 err_code |= ERR_ALERT | ERR_ABORT;
3096 goto out;
3097 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003098 } else if (!strcmp(args[1], "show-node")) {
3099
3100 if (*args[2]) {
3101 int i;
3102 char c;
3103
3104 for (i=0; args[2][i]; i++) {
3105 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003106 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3107 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003108 break;
3109 }
3110
3111 if (!i || args[2][i]) {
3112 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3113 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3114 file, linenum, args[0], args[1]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
3117 }
3118 }
3119
3120 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3121 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
3124 }
3125 } else if (!strcmp(args[1], "show-desc")) {
3126 char *desc = NULL;
3127
3128 if (*args[2]) {
3129 int i, len=0;
3130 char *d;
3131
3132 for(i=2; *args[i]; i++)
3133 len += strlen(args[i])+1;
3134
3135 desc = d = (char *)calloc(1, len);
3136
3137 d += sprintf(d, "%s", args[2]);
3138 for(i=3; *args[i]; i++)
3139 d += sprintf(d, " %s", args[i]);
3140 }
3141
3142 if (!*args[2] && !global.desc)
3143 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3144 file, linenum, args[1]);
3145 else {
3146 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3147 free(desc);
3148 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3149 err_code |= ERR_ALERT | ERR_ABORT;
3150 goto out;
3151 }
3152 free(desc);
3153 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003155stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003156 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 +01003157 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003158 err_code |= ERR_ALERT | ERR_FATAL;
3159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 }
3161 }
3162 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003163 int optnum;
3164
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003165 if (*(args[1]) == '\0') {
3166 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3167 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003171
3172 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3173 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003174 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3175 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3176 file, linenum, cfg_opts[optnum].name);
3177 err_code |= ERR_ALERT | ERR_FATAL;
3178 goto out;
3179 }
Willy Tarreau93893792009-07-23 13:19:11 +02003180 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3181 err_code |= ERR_WARN;
3182 goto out;
3183 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003184
Willy Tarreau3842f002009-06-14 11:39:52 +02003185 curproxy->no_options &= ~cfg_opts[optnum].val;
3186 curproxy->options &= ~cfg_opts[optnum].val;
3187
3188 switch (kwm) {
3189 case KWM_STD:
3190 curproxy->options |= cfg_opts[optnum].val;
3191 break;
3192 case KWM_NO:
3193 curproxy->no_options |= cfg_opts[optnum].val;
3194 break;
3195 case KWM_DEF: /* already cleared */
3196 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003197 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003198
Willy Tarreau93893792009-07-23 13:19:11 +02003199 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003200 }
3201 }
3202
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003203 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3204 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003205 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3206 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3207 file, linenum, cfg_opts2[optnum].name);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
Willy Tarreau93893792009-07-23 13:19:11 +02003211 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3212 err_code |= ERR_WARN;
3213 goto out;
3214 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003215
Willy Tarreau3842f002009-06-14 11:39:52 +02003216 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3217 curproxy->options2 &= ~cfg_opts2[optnum].val;
3218
3219 switch (kwm) {
3220 case KWM_STD:
3221 curproxy->options2 |= cfg_opts2[optnum].val;
3222 break;
3223 case KWM_NO:
3224 curproxy->no_options2 |= cfg_opts2[optnum].val;
3225 break;
3226 case KWM_DEF: /* already cleared */
3227 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003228 }
Willy Tarreau93893792009-07-23 13:19:11 +02003229 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003230 }
3231 }
3232
Willy Tarreau3842f002009-06-14 11:39:52 +02003233 if (kwm != KWM_STD) {
3234 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003235 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003238 }
3239
Emeric Brun3a058f32009-06-30 18:26:00 +02003240 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003242 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003244 if (*(args[2]) != '\0') {
3245 if (!strcmp(args[2], "clf")) {
3246 curproxy->options2 |= PR_O2_CLFLOG;
3247 } else {
3248 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003251 }
3252 }
3253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003254 else if (!strcmp(args[1], "tcplog"))
3255 /* generate a detailed TCP log */
3256 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003257 else if (!strcmp(args[1], "tcpka")) {
3258 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003259 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003261
3262 if (curproxy->cap & PR_CAP_FE)
3263 curproxy->options |= PR_O_TCP_CLI_KA;
3264 if (curproxy->cap & PR_CAP_BE)
3265 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
3267 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003268 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_WARN;
3270
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003272 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003273 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003274 curproxy->options2 &= ~PR_O2_CHK_ANY;
3275 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 if (!*args[2]) { /* no argument */
3277 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3278 curproxy->check_len = strlen(DEF_CHECK_REQ);
3279 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003280 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 curproxy->check_req = (char *)malloc(reqlen);
3282 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003283 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003285 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 if (*args[4])
3287 reqlen += strlen(args[4]);
3288 else
3289 reqlen += strlen("HTTP/1.0");
3290
3291 curproxy->check_req = (char *)malloc(reqlen);
3292 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003293 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003295 }
3296 else if (!strcmp(args[1], "ssl-hello-chk")) {
3297 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003298 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003300
Willy Tarreaua534fea2008-08-03 12:19:50 +02003301 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003302 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003303 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003304 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
Willy Tarreau23677902007-05-08 23:50:35 +02003306 else if (!strcmp(args[1], "smtpchk")) {
3307 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003308 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003309 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003310 curproxy->options2 &= ~PR_O2_CHK_ANY;
3311 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003312
3313 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3314 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3315 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3316 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3317 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3318 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3319 curproxy->check_req = (char *)malloc(reqlen);
3320 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3321 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3322 } else {
3323 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3324 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3325 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3326 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3327 }
3328 }
3329 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003330 else if (!strcmp(args[1], "pgsql-check")) {
3331 /* use PostgreSQL request to check servers' health */
3332 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3333 err_code |= ERR_WARN;
3334
3335 free(curproxy->check_req);
3336 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003337 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003338 curproxy->options2 |= PR_O2_PGSQL_CHK;
3339
3340 if (*(args[2])) {
3341 int cur_arg = 2;
3342
3343 while (*(args[cur_arg])) {
3344 if (strcmp(args[cur_arg], "user") == 0) {
3345 char * packet;
3346 uint32_t packet_len;
3347 uint32_t pv;
3348
3349 /* suboption header - needs additional argument for it */
3350 if (*(args[cur_arg+1]) == 0) {
3351 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3352 file, linenum, args[0], args[1], args[cur_arg]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3358 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3359 pv = htonl(0x30000); /* protocol version 3.0 */
3360
3361 packet = (char*) calloc(1, packet_len);
3362
3363 memcpy(packet + 4, &pv, 4);
3364
3365 /* copy "user" */
3366 memcpy(packet + 8, "user", 4);
3367
3368 /* copy username */
3369 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3370
3371 free(curproxy->check_req);
3372 curproxy->check_req = packet;
3373 curproxy->check_len = packet_len;
3374
3375 packet_len = htonl(packet_len);
3376 memcpy(packet, &packet_len, 4);
3377 cur_arg += 2;
3378 } else {
3379 /* unknown suboption - catchall */
3380 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3381 file, linenum, args[0], args[1]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385 } /* end while loop */
3386 }
3387 }
3388
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003389 else if (!strcmp(args[1], "redis-check")) {
3390 /* use REDIS PING request to check servers' health */
3391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3392 err_code |= ERR_WARN;
3393
3394 free(curproxy->check_req);
3395 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003396 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003397 curproxy->options2 |= PR_O2_REDIS_CHK;
3398
3399 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3400 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3401 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3402 }
3403
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003404 else if (!strcmp(args[1], "mysql-check")) {
3405 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003406 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3407 err_code |= ERR_WARN;
3408
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003409 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003410 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003411 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003412 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003413
3414 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3415 * const char mysql40_client_auth_pkt[] = {
3416 * "\x0e\x00\x00" // packet length
3417 * "\x01" // packet number
3418 * "\x00\x00" // client capabilities
3419 * "\x00\x00\x01" // max packet
3420 * "haproxy\x00" // username (null terminated string)
3421 * "\x00" // filler (always 0x00)
3422 * "\x01\x00\x00" // packet length
3423 * "\x00" // packet number
3424 * "\x01" // COM_QUIT command
3425 * };
3426 */
3427
3428 if (*(args[2])) {
3429 int cur_arg = 2;
3430
3431 while (*(args[cur_arg])) {
3432 if (strcmp(args[cur_arg], "user") == 0) {
3433 char *mysqluser;
3434 int packetlen, reqlen, userlen;
3435
3436 /* suboption header - needs additional argument for it */
3437 if (*(args[cur_arg+1]) == 0) {
3438 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3439 file, linenum, args[0], args[1], args[cur_arg]);
3440 err_code |= ERR_ALERT | ERR_FATAL;
3441 goto out;
3442 }
3443 mysqluser = args[cur_arg + 1];
3444 userlen = strlen(mysqluser);
3445 packetlen = userlen + 7;
3446 reqlen = packetlen + 9;
3447
3448 free(curproxy->check_req);
3449 curproxy->check_req = (char *)calloc(1, reqlen);
3450 curproxy->check_len = reqlen;
3451
3452 snprintf(curproxy->check_req, 4, "%c%c%c",
3453 ((unsigned char) packetlen & 0xff),
3454 ((unsigned char) (packetlen >> 8) & 0xff),
3455 ((unsigned char) (packetlen >> 16) & 0xff));
3456
3457 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003458 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003459 curproxy->check_req[8] = 1;
3460 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3461 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3462 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3463 cur_arg += 2;
3464 } else {
3465 /* unknown suboption - catchall */
3466 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3467 file, linenum, args[0], args[1]);
3468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
3470 }
3471 } /* end while loop */
3472 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003473 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003474 else if (!strcmp(args[1], "ldap-check")) {
3475 /* use LDAP request to check servers' health */
3476 free(curproxy->check_req);
3477 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003478 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003479 curproxy->options2 |= PR_O2_LDAP_CHK;
3480
3481 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3482 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3483 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3484 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003485 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003486 int cur_arg;
3487
3488 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3489 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003490 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003491
Willy Tarreau87cf5142011-08-19 22:57:24 +02003492 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003493
3494 free(curproxy->fwdfor_hdr_name);
3495 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3496 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3497
3498 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3499 cur_arg = 2;
3500 while (*(args[cur_arg])) {
3501 if (!strcmp(args[cur_arg], "except")) {
3502 /* suboption except - needs additional argument for it */
3503 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3504 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3505 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003508 }
3509 /* flush useless bits */
3510 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003511 cur_arg += 2;
3512 } else if (!strcmp(args[cur_arg], "header")) {
3513 /* suboption header - needs additional argument for it */
3514 if (*(args[cur_arg+1]) == 0) {
3515 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3516 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003519 }
3520 free(curproxy->fwdfor_hdr_name);
3521 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3522 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3523 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003524 } else if (!strcmp(args[cur_arg], "if-none")) {
3525 curproxy->options &= ~PR_O_FF_ALWAYS;
3526 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003527 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003528 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003529 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003530 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003531 err_code |= ERR_ALERT | ERR_FATAL;
3532 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003533 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003534 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003535 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003536 else if (!strcmp(args[1], "originalto")) {
3537 int cur_arg;
3538
3539 /* insert x-original-to field, but not for the IP address listed as an except.
3540 * set default options (ie: bitfield, header name, etc)
3541 */
3542
3543 curproxy->options |= PR_O_ORGTO;
3544
3545 free(curproxy->orgto_hdr_name);
3546 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3547 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3548
Willy Tarreau87cf5142011-08-19 22:57:24 +02003549 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003550 cur_arg = 2;
3551 while (*(args[cur_arg])) {
3552 if (!strcmp(args[cur_arg], "except")) {
3553 /* suboption except - needs additional argument for it */
3554 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3555 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3556 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003559 }
3560 /* flush useless bits */
3561 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3562 cur_arg += 2;
3563 } else if (!strcmp(args[cur_arg], "header")) {
3564 /* suboption header - needs additional argument for it */
3565 if (*(args[cur_arg+1]) == 0) {
3566 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3567 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003570 }
3571 free(curproxy->orgto_hdr_name);
3572 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3573 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3574 cur_arg += 2;
3575 } else {
3576 /* unknown suboption - catchall */
3577 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3578 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003581 }
3582 } /* end while loop */
3583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 else {
3585 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
Willy Tarreau93893792009-07-23 13:19:11 +02003589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003591 else if (!strcmp(args[0], "default_backend")) {
3592 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003594
3595 if (*(args[1]) == 0) {
3596 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003599 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003600 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003601 curproxy->defbe.name = strdup(args[1]);
3602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003604 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003606
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003607 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3608 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 /* enable reconnections to dispatch */
3611 curproxy->options |= PR_O_REDISP;
3612 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003613 else if (!strcmp(args[0], "http-check")) {
3614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003616
3617 if (strcmp(args[1], "disable-on-404") == 0) {
3618 /* enable a graceful server shutdown on an HTTP 404 response */
3619 curproxy->options |= PR_O_DISABLE404;
3620 }
Willy Tarreauef781042010-01-27 11:53:01 +01003621 else if (strcmp(args[1], "send-state") == 0) {
3622 /* enable emission of the apparent state of a server in HTTP checks */
3623 curproxy->options2 |= PR_O2_CHK_SNDST;
3624 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003625 else if (strcmp(args[1], "expect") == 0) {
3626 const char *ptr_arg;
3627 int cur_arg;
3628
3629 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3630 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634
3635 cur_arg = 2;
3636 /* consider exclamation marks, sole or at the beginning of a word */
3637 while (*(ptr_arg = args[cur_arg])) {
3638 while (*ptr_arg == '!') {
3639 curproxy->options2 ^= PR_O2_EXP_INV;
3640 ptr_arg++;
3641 }
3642 if (*ptr_arg)
3643 break;
3644 cur_arg++;
3645 }
3646 /* now ptr_arg points to the beginning of a word past any possible
3647 * exclamation mark, and cur_arg is the argument which holds this word.
3648 */
3649 if (strcmp(ptr_arg, "status") == 0) {
3650 if (!*(args[cur_arg + 1])) {
3651 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3652 file, linenum, args[0], args[1], ptr_arg);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003657 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003658 curproxy->expect_str = strdup(args[cur_arg + 1]);
3659 }
3660 else if (strcmp(ptr_arg, "string") == 0) {
3661 if (!*(args[cur_arg + 1])) {
3662 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3663 file, linenum, args[0], args[1], ptr_arg);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
3667 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003668 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003669 curproxy->expect_str = strdup(args[cur_arg + 1]);
3670 }
3671 else if (strcmp(ptr_arg, "rstatus") == 0) {
3672 if (!*(args[cur_arg + 1])) {
3673 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3674 file, linenum, args[0], args[1], ptr_arg);
3675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
3677 }
3678 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003679 free(curproxy->expect_str);
3680 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3681 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003682 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3683 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3684 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3685 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689 }
3690 else if (strcmp(ptr_arg, "rstring") == 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_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003698 free(curproxy->expect_str);
3699 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3700 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003701 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3702 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3703 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3704 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
3708 }
3709 else {
3710 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3711 file, linenum, args[0], args[1], ptr_arg);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003716 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003717 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003720 }
3721 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003722 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003723 if (curproxy == &defproxy) {
3724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003727 }
3728
Willy Tarreaub80c2302007-11-30 20:51:32 +01003729 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003731
3732 if (strcmp(args[1], "fail") == 0) {
3733 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003734 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003735 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3736 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003739 }
3740
Willy Tarreauef6494c2010-01-28 17:12:36 +01003741 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003742 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3743 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003746 }
3747 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3748 }
3749 else {
3750 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 }
3754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003755#ifdef TPROXY
3756 else if (!strcmp(args[0], "transparent")) {
3757 /* enable transparent proxy connections */
3758 curproxy->options |= PR_O_TRANSP;
3759 }
3760#endif
3761 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003762 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003764
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 if (*(args[1]) == 0) {
3766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 }
3770 curproxy->maxconn = atol(args[1]);
3771 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003772 else if (!strcmp(args[0], "backlog")) { /* backlog */
3773 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003775
3776 if (*(args[1]) == 0) {
3777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003780 }
3781 curproxy->backlog = atol(args[1]);
3782 }
Willy Tarreau86034312006-12-29 00:10:33 +01003783 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003786
Willy Tarreau86034312006-12-29 00:10:33 +01003787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003791 }
3792 curproxy->fullconn = atol(args[1]);
3793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3795 if (*(args[1]) == 0) {
3796 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_ALERT | ERR_FATAL;
3798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003799 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003800 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3801 if (err) {
3802 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3803 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003806 }
3807 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
3809 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003810 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 if (curproxy == &defproxy) {
3812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003816 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003818
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 if (strchr(args[1], ':') == NULL) {
3820 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003824 sk = str2sa(args[1]);
3825 if (!sk) {
3826 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
3829 }
3830 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003831 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
3833 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003836
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003837 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003838 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3839 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003844 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3845 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3846 err_code |= ERR_WARN;
3847
3848 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3849 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3850 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3851 }
3852 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3853 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3854 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3855 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003856 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3857 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3858 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3859 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003860 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003861 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
3865 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003866 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003868 char *rport, *raddr;
3869 short realport = 0;
3870 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003872 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003877 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879
3880 if (!*args[2]) {
3881 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3882 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003886
3887 err = invalid_char(args[1]);
3888 if (err) {
3889 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3890 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003893 }
3894
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003895 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003896 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003897
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003898 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3899 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3900 err_code |= ERR_ALERT | ERR_ABORT;
3901 goto out;
3902 }
3903
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003904 /* the servers are linked backwards first */
3905 newsrv->next = curproxy->srv;
3906 curproxy->srv = newsrv;
3907 newsrv->proxy = curproxy;
3908 newsrv->conf.file = file;
3909 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003910
Simon Hormanaf514952011-06-21 14:34:57 +09003911 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 LIST_INIT(&newsrv->pendconns);
3913 do_check = 0;
3914 newsrv->state = SRV_RUNNING; /* early server setup */
3915 newsrv->last_change = now.tv_sec;
3916 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003918 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003919 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 * - IP: => port=+0, relative
3921 * - IP:N => port=N, absolute
3922 * - IP:+N => port=+N, relative
3923 * - IP:-N => port=-N, relative
3924 */
3925 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003926 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003927 if (rport) {
3928 *rport++ = 0;
3929 realport = atol(rport);
3930 if (!isdigit((unsigned char)*rport))
3931 newsrv->state |= SRV_MAPPORTS;
3932 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934
Willy Tarreaufab5a432011-03-04 15:31:53 +01003935 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003937 if (!sk) {
3938 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
3942 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003943 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944
3945 newsrv->check_port = curproxy->defsrv.check_port;
3946 newsrv->inter = curproxy->defsrv.inter;
3947 newsrv->fastinter = curproxy->defsrv.fastinter;
3948 newsrv->downinter = curproxy->defsrv.downinter;
3949 newsrv->rise = curproxy->defsrv.rise;
3950 newsrv->fall = curproxy->defsrv.fall;
3951 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3952 newsrv->minconn = curproxy->defsrv.minconn;
3953 newsrv->maxconn = curproxy->defsrv.maxconn;
3954 newsrv->slowstart = curproxy->defsrv.slowstart;
3955 newsrv->onerror = curproxy->defsrv.onerror;
3956 newsrv->consecutive_errors_limit
3957 = curproxy->defsrv.consecutive_errors_limit;
3958 newsrv->uweight = newsrv->iweight
3959 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961 newsrv->curfd = -1; /* no health-check in progress */
3962 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003963
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003964 cur_arg = 3;
3965 } else {
3966 newsrv = &curproxy->defsrv;
3967 cur_arg = 1;
3968 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003969
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003972 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003973
3974 if (!*args[cur_arg + 1]) {
3975 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3976 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003979 }
3980
3981 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003982 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003983
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003984 if (newsrv->puid <= 0) {
3985 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003986 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003989 }
3990
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003991 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3992 if (node) {
3993 struct server *target = container_of(node, struct server, conf.id);
3994 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3995 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
3998 }
3999 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004000 cur_arg += 2;
4001 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004003 newsrv->cookie = strdup(args[cur_arg + 1]);
4004 newsrv->cklen = strlen(args[cur_arg + 1]);
4005 cur_arg += 2;
4006 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004007 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004008 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4009 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4010 cur_arg += 2;
4011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004013 if (!*args[cur_arg + 1]) {
4014 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4015 file, linenum, args[cur_arg]);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004021 if (newsrv->rise <= 0) {
4022 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4023 file, linenum, args[cur_arg]);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026 }
4027
Willy Tarreau96839092010-03-29 10:02:24 +02004028 if (newsrv->health)
4029 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 cur_arg += 2;
4031 }
4032 else if (!strcmp(args[cur_arg], "fall")) {
4033 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004034
4035 if (!*args[cur_arg + 1]) {
4036 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4037 file, linenum, args[cur_arg]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
4042 if (newsrv->fall <= 0) {
4043 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4044 file, linenum, args[cur_arg]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
4048
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 cur_arg += 2;
4050 }
4051 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004052 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4053 if (err) {
4054 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4055 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004058 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004059 if (val <= 0) {
4060 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4061 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004064 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004065 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004066 cur_arg += 2;
4067 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004068 else if (!strcmp(args[cur_arg], "fastinter")) {
4069 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4070 if (err) {
4071 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4072 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004075 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004076 if (val <= 0) {
4077 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4078 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004079 err_code |= ERR_ALERT | ERR_FATAL;
4080 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004081 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004082 newsrv->fastinter = val;
4083 cur_arg += 2;
4084 }
4085 else if (!strcmp(args[cur_arg], "downinter")) {
4086 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4087 if (err) {
4088 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4089 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004092 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004093 if (val <= 0) {
4094 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4095 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004098 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004099 newsrv->downinter = val;
4100 cur_arg += 2;
4101 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004102 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004103 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004104 if (!sk) {
4105 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004110 cur_arg += 2;
4111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112 else if (!strcmp(args[cur_arg], "port")) {
4113 newsrv->check_port = atol(args[cur_arg + 1]);
4114 cur_arg += 2;
4115 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004116 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 newsrv->state |= SRV_BACKUP;
4118 cur_arg ++;
4119 }
Simon Hormanfa461682011-06-25 09:39:49 +09004120 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4121 newsrv->state |= SRV_NON_STICK;
4122 cur_arg ++;
4123 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004124 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4125 newsrv->state |= SRV_SEND_PROXY;
4126 cur_arg ++;
4127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 else if (!strcmp(args[cur_arg], "weight")) {
4129 int w;
4130 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004131 if (w < 0 || w > 256) {
4132 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004137 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 cur_arg += 2;
4139 }
4140 else if (!strcmp(args[cur_arg], "minconn")) {
4141 newsrv->minconn = atol(args[cur_arg + 1]);
4142 cur_arg += 2;
4143 }
4144 else if (!strcmp(args[cur_arg], "maxconn")) {
4145 newsrv->maxconn = atol(args[cur_arg + 1]);
4146 cur_arg += 2;
4147 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004148 else if (!strcmp(args[cur_arg], "maxqueue")) {
4149 newsrv->maxqueue = atol(args[cur_arg + 1]);
4150 cur_arg += 2;
4151 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004152 else if (!strcmp(args[cur_arg], "slowstart")) {
4153 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004154 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004155 if (err) {
4156 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4157 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004160 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004161 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004162 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4163 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004164 err_code |= ERR_ALERT | ERR_FATAL;
4165 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004166 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004167 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004168 cur_arg += 2;
4169 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004170 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004171
4172 if (!*args[cur_arg + 1]) {
4173 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4174 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004175 err_code |= ERR_ALERT | ERR_FATAL;
4176 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004177 }
4178
4179 newsrv->trackit = strdup(args[cur_arg + 1]);
4180
4181 cur_arg += 2;
4182 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004183 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 global.maxsock++;
4185 do_check = 1;
4186 cur_arg += 1;
4187 }
Willy Tarreau96839092010-03-29 10:02:24 +02004188 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4189 newsrv->state |= SRV_MAINTAIN;
4190 newsrv->state &= ~SRV_RUNNING;
4191 newsrv->health = 0;
4192 cur_arg += 1;
4193 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004194 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004195 if (!strcmp(args[cur_arg + 1], "none"))
4196 newsrv->observe = HANA_OBS_NONE;
4197 else if (!strcmp(args[cur_arg + 1], "layer4"))
4198 newsrv->observe = HANA_OBS_LAYER4;
4199 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4200 if (curproxy->mode != PR_MODE_HTTP) {
4201 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4202 file, linenum, args[cur_arg + 1]);
4203 err_code |= ERR_ALERT;
4204 }
4205 newsrv->observe = HANA_OBS_LAYER7;
4206 }
4207 else {
4208 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004209 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004210 file, linenum, args[cur_arg], args[cur_arg + 1]);
4211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
4213 }
4214
4215 cur_arg += 2;
4216 }
4217 else if (!strcmp(args[cur_arg], "on-error")) {
4218 if (!strcmp(args[cur_arg + 1], "fastinter"))
4219 newsrv->onerror = HANA_ONERR_FASTINTER;
4220 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4221 newsrv->onerror = HANA_ONERR_FAILCHK;
4222 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4223 newsrv->onerror = HANA_ONERR_SUDDTH;
4224 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4225 newsrv->onerror = HANA_ONERR_MARKDWN;
4226 else {
4227 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004228 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004229 file, linenum, args[cur_arg], args[cur_arg + 1]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
4234 cur_arg += 2;
4235 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004236 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4237 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4238 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4239 else {
4240 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4241 file, linenum, args[cur_arg], args[cur_arg + 1]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 }
4245
4246 cur_arg += 2;
4247 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004248 else if (!strcmp(args[cur_arg], "error-limit")) {
4249 if (!*args[cur_arg + 1]) {
4250 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4251 file, linenum, args[cur_arg]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4257
4258 if (newsrv->consecutive_errors_limit <= 0) {
4259 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4260 file, linenum, args[cur_arg]);
4261 err_code |= ERR_ALERT | ERR_FATAL;
4262 goto out;
4263 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004264 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004265 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004266 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004267 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004268 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004269
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004271#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004272 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004273 file, linenum, "source", "usesrc");
4274#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004275 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004277#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 }
4281 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004282 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4283 if (!sk) {
4284 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
4288 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004289
4290 if (port_low != port_high) {
4291 int i;
4292 if (port_low <= 0 || port_low > 65535 ||
4293 port_high <= 0 || port_high > 65535 ||
4294 port_low > port_high) {
4295 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4296 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004299 }
4300 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4301 for (i = 0; i < newsrv->sport_range->size; i++)
4302 newsrv->sport_range->ports[i] = port_low + i;
4303 }
4304
Willy Tarreaubaaee002006-06-26 02:48:02 +02004305 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004306 while (*(args[cur_arg])) {
4307 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004308#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4309#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004310 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4311 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4312 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004315 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004316#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004317 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004318 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004319 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 }
4323 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004324 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 newsrv->state |= SRV_TPROXY_CLI;
4326 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004327 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004329 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4330 char *name, *end;
4331
4332 name = args[cur_arg+1] + 7;
4333 while (isspace(*name))
4334 name++;
4335
4336 end = name;
4337 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4338 end++;
4339
4340 newsrv->state &= ~SRV_TPROXY_MASK;
4341 newsrv->state |= SRV_TPROXY_DYN;
4342 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4343 newsrv->bind_hdr_len = end - name;
4344 memcpy(newsrv->bind_hdr_name, name, end - name);
4345 newsrv->bind_hdr_name[end-name] = '\0';
4346 newsrv->bind_hdr_occ = -1;
4347
4348 /* now look for an occurrence number */
4349 while (isspace(*end))
4350 end++;
4351 if (*end == ',') {
4352 end++;
4353 name = end;
4354 if (*end == '-')
4355 end++;
4356 while (isdigit(*end))
4357 end++;
4358 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4359 }
4360
4361 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4362 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4363 " occurrences values smaller than %d.\n",
4364 file, linenum, MAX_HDR_HISTORY);
4365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
4367 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004368 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004369 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004370 if (!sk) {
4371 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004377 }
4378 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004379#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004381#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004382 cur_arg += 2;
4383 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004384#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004386 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4390 } /* "usesrc" */
4391
4392 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4393#ifdef SO_BINDTODEVICE
4394 if (!*args[cur_arg + 1]) {
4395 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4396 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004399 }
4400 if (newsrv->iface_name)
4401 free(newsrv->iface_name);
4402
4403 newsrv->iface_name = strdup(args[cur_arg + 1]);
4404 newsrv->iface_len = strlen(newsrv->iface_name);
4405 global.last_checks |= LSTCHK_NETADM;
4406#else
4407 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4408 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004411#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004412 cur_arg += 2;
4413 continue;
4414 }
4415 /* this keyword in not an option of "source" */
4416 break;
4417 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004418 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004419 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004420 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4421 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004426 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004427 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004428 file, linenum, newsrv->id);
4429 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004430 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 +01004431 file, linenum);
4432
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 }
4436 }
4437
4438 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004439 if (newsrv->trackit) {
4440 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4441 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004444 }
4445
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004446 /* try to get the port from check_addr if check_port not set */
4447 if (!newsrv->check_port)
4448 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004449
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4451 newsrv->check_port = realport; /* by default */
4452 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004453 /* not yet valid, because no port was set on
4454 * the server either. We'll check if we have
4455 * a known port on the first listener.
4456 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004457 struct listener *l = curproxy->listen;
4458 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4459 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004460 }
4461 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4463 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004467
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004468 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004469 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004470 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4471 err_code |= ERR_ALERT | ERR_ABORT;
4472 goto out;
4473 }
4474
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004475 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 newsrv->state |= SRV_CHECKED;
4477 }
4478
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004479 if (!defsrv) {
4480 if (newsrv->state & SRV_BACKUP)
4481 curproxy->srv_bck++;
4482 else
4483 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004484
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004485 newsrv->prev_state = newsrv->state;
4486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004487 }
4488 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004489 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 int facility;
4491
4492 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4493 curproxy->logfac1 = global.logfac1;
4494 curproxy->logsrv1 = global.logsrv1;
4495 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004496 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 curproxy->logfac2 = global.logfac2;
4498 curproxy->logsrv2 = global.logsrv2;
4499 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004500 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 }
4502 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004503 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504
4505 facility = get_log_facility(args[2]);
4506 if (facility < 0) {
4507 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4508 exit(1);
4509 }
4510
4511 level = 7; /* max syslog level = debug */
4512 if (*(args[3])) {
4513 level = get_log_level(args[3]);
4514 if (level < 0) {
4515 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4516 exit(1);
4517 }
4518 }
4519
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004520 minlvl = 0; /* limit syslog level to this level (emerg) */
4521 if (*(args[4])) {
4522 minlvl = get_log_level(args[4]);
4523 if (level < 0) {
4524 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4525 exit(1);
4526 }
4527 }
4528
Robert Tsai81ae1952007-12-05 10:47:29 +01004529 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004530 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004531 if (!sk) {
4532 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004533 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
4536 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004537 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004538 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004539 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004540 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004541 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004545 logsrv.addr = *sk;
4546 if (!get_host_port(&logsrv.addr))
4547 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549
4550 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004551 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552 curproxy->logfac1 = facility;
4553 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004554 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 }
4556 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004557 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004558 curproxy->logfac2 = facility;
4559 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004560 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 }
4562 else {
4563 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566 }
4567 }
4568 else {
4569 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4570 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574 }
4575 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004576 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004577 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004578
Willy Tarreau977b8e42006-12-29 14:19:17 +01004579 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004581
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004583 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4584 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004588
4589 /* we must first clear any optional default setting */
4590 curproxy->options &= ~PR_O_TPXY_MASK;
4591 free(curproxy->iface_name);
4592 curproxy->iface_name = NULL;
4593 curproxy->iface_len = 0;
4594
Willy Tarreaud5191e72010-02-09 20:50:45 +01004595 sk = str2sa(args[1]);
4596 if (!sk) {
4597 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004603
4604 cur_arg = 2;
4605 while (*(args[cur_arg])) {
4606 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004607#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4608#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004609 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4610 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4611 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004614 }
4615#endif
4616 if (!*args[cur_arg + 1]) {
4617 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4618 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004621 }
4622
4623 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004624 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004625 curproxy->options |= PR_O_TPXY_CLI;
4626 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004627 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004628 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004629 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4630 char *name, *end;
4631
4632 name = args[cur_arg+1] + 7;
4633 while (isspace(*name))
4634 name++;
4635
4636 end = name;
4637 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4638 end++;
4639
4640 curproxy->options &= ~PR_O_TPXY_MASK;
4641 curproxy->options |= PR_O_TPXY_DYN;
4642 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4643 curproxy->bind_hdr_len = end - name;
4644 memcpy(curproxy->bind_hdr_name, name, end - name);
4645 curproxy->bind_hdr_name[end-name] = '\0';
4646 curproxy->bind_hdr_occ = -1;
4647
4648 /* now look for an occurrence number */
4649 while (isspace(*end))
4650 end++;
4651 if (*end == ',') {
4652 end++;
4653 name = end;
4654 if (*end == '-')
4655 end++;
4656 while (isdigit(*end))
4657 end++;
4658 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4659 }
4660
4661 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4662 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4663 " occurrences values smaller than %d.\n",
4664 file, linenum, MAX_HDR_HISTORY);
4665 err_code |= ERR_ALERT | ERR_FATAL;
4666 goto out;
4667 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004668 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004669 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004670 if (!sk) {
4671 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004676 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004677 }
4678 global.last_checks |= LSTCHK_NETADM;
4679#if !defined(CONFIG_HAP_LINUX_TPROXY)
4680 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004681#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004682#else /* no TPROXY support */
4683 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004684 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004687#endif
4688 cur_arg += 2;
4689 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004690 }
4691
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4693#ifdef SO_BINDTODEVICE
4694 if (!*args[cur_arg + 1]) {
4695 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 }
4700 if (curproxy->iface_name)
4701 free(curproxy->iface_name);
4702
4703 curproxy->iface_name = strdup(args[cur_arg + 1]);
4704 curproxy->iface_len = strlen(curproxy->iface_name);
4705 global.last_checks |= LSTCHK_NETADM;
4706#else
4707 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4708 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004711#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004712 cur_arg += 2;
4713 continue;
4714 }
4715 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4716 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004721 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4722 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4723 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004728 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004734
4735 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4736 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004737 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004738 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 }
4741 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004742 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4743 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004744 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004745 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 }
4748 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004749 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4750 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004751 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 }
4755 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4757 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004758 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
4762 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004763 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4764 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004765 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004769 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004770 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4771 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004772 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004774 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004775 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004776 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004777 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4778 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004779 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004781 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004782 }
4783 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4785 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004786 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004788 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004791 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4793 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797
4798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4799 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004800 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 }
4804 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4806 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004807 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 }
4811 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4813 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004814 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 }
4818 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4820 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004821 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
4825 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4827 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004828 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004832 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4834 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004835 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004837 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004839 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004840 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004841
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 if (curproxy == &defproxy) {
4843 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004846 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004847 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004848 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 if (*(args[1]) == 0) {
4851 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004855
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004856 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4857 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4858 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4859 file, linenum, args[0]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4864 }
4865 else if (*args[2]) {
4866 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4867 file, linenum, args[0], args[2]);
4868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
4871
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004872 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004873 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004874 wl->s = strdup(args[1]);
4875 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004876 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
4878 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004879 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4881 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004885
Willy Tarreauade5ec42010-01-28 19:33:49 +01004886 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4887 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004888 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004889 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 }
4892 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004893 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4894 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004895 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004900 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4901 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004902 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
4906 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 }
4913
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4915 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004916 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
4920 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4922 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004923 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 }
4927 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4929 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004930 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
4934 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004935 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004936
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 if (curproxy == &defproxy) {
4938 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004942 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 if (*(args[1]) == 0) {
4946 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004951 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4952 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4953 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4954 file, linenum, args[0]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
4958 err_code |= warnif_cond_requires_req(cond, file, linenum);
4959 }
4960 else if (*args[2]) {
4961 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4962 file, linenum, args[0], args[2]);
4963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
4965 }
4966
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004967 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004968 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004969 wl->s = strdup(args[1]);
4970 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 }
4972 else if (!strcmp(args[0], "errorloc") ||
4973 !strcmp(args[0], "errorloc302") ||
4974 !strcmp(args[0], "errorloc303")) { /* error location */
4975 int errnum, errlen;
4976 char *err;
4977
Willy Tarreau977b8e42006-12-29 14:19:17 +01004978 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004980
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004982 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
4986
4987 errnum = atol(args[1]);
4988 if (!strcmp(args[0], "errorloc303")) {
4989 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4990 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4991 } else {
4992 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4993 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4994 }
4995
Willy Tarreau0f772532006-12-23 20:51:41 +01004996 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4997 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004998 chunk_destroy(&curproxy->errmsg[rc]);
4999 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005000 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005002 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005003
5004 if (rc >= HTTP_ERR_SIZE) {
5005 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5006 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 free(err);
5008 }
5009 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005010 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5011 int errnum, errlen, fd;
5012 char *err;
5013 struct stat stat;
5014
5015 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005017
5018 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005019 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005022 }
5023
5024 fd = open(args[2], O_RDONLY);
5025 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5026 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5027 file, linenum, args[2], args[1]);
5028 if (fd >= 0)
5029 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005032 }
5033
Willy Tarreau27a674e2009-08-17 07:23:33 +02005034 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005035 errlen = stat.st_size;
5036 } else {
5037 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005038 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005040 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005041 }
5042
5043 err = malloc(errlen); /* malloc() must succeed during parsing */
5044 errnum = read(fd, err, errlen);
5045 if (errnum != errlen) {
5046 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5047 file, linenum, args[2], args[1]);
5048 close(fd);
5049 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005052 }
5053 close(fd);
5054
5055 errnum = atol(args[1]);
5056 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5057 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005058 chunk_destroy(&curproxy->errmsg[rc]);
5059 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005060 break;
5061 }
5062 }
5063
5064 if (rc >= HTTP_ERR_SIZE) {
5065 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5066 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005068 free(err);
5069 }
5070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005071 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005072 struct cfg_kw_list *kwl;
5073 int index;
5074
5075 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5076 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5077 if (kwl->kw[index].section != CFG_LISTEN)
5078 continue;
5079 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5080 /* prepare error message just in case */
5081 snprintf(trash, sizeof(trash),
5082 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005083 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5084 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005085 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005088 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005089 else if (rc > 0) {
5090 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_WARN;
5092 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005093 }
Willy Tarreau93893792009-07-23 13:19:11 +02005094 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005095 }
5096 }
5097 }
5098
Willy Tarreau6daf3432008-01-22 16:44:08 +01005099 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Willy Tarreau93893792009-07-23 13:19:11 +02005103 out:
5104 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105}
5106
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005107int
5108cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5109{
5110
5111 int err_code = 0;
5112 const char *err;
5113
5114 if (!strcmp(args[0], "userlist")) { /* new userlist */
5115 struct userlist *newul;
5116
5117 if (!*args[1]) {
5118 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5119 file, linenum, args[0]);
5120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
5123
5124 err = invalid_char(args[1]);
5125 if (err) {
5126 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5127 file, linenum, *err, args[0], args[1]);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
5131
5132 for (newul = userlist; newul; newul = newul->next)
5133 if (!strcmp(newul->name, args[1])) {
5134 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5135 file, linenum, args[1]);
5136 err_code |= ERR_WARN;
5137 goto out;
5138 }
5139
5140 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5141 if (!newul) {
5142 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5143 err_code |= ERR_ALERT | ERR_ABORT;
5144 goto out;
5145 }
5146
5147 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5148 newul->name = strdup(args[1]);
5149
5150 if (!newul->groupusers | !newul->name) {
5151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5152 err_code |= ERR_ALERT | ERR_ABORT;
5153 goto out;
5154 }
5155
5156 newul->next = userlist;
5157 userlist = newul;
5158
5159 } else if (!strcmp(args[0], "group")) { /* new group */
5160 int cur_arg, i;
5161 const char *err;
5162
5163 if (!*args[1]) {
5164 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5165 file, linenum, args[0]);
5166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
5168 }
5169
5170 err = invalid_char(args[1]);
5171 if (err) {
5172 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5173 file, linenum, *err, args[0], args[1]);
5174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
5176 }
5177
5178 for(i = 0; i < userlist->grpcnt; i++)
5179 if (!strcmp(userlist->groups[i], args[1])) {
5180 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5181 file, linenum, args[1], userlist->name);
5182 err_code |= ERR_ALERT;
5183 goto out;
5184 }
5185
5186 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5187 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5188 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
5191 }
5192
5193 cur_arg = 2;
5194
5195 while (*args[cur_arg]) {
5196 if (!strcmp(args[cur_arg], "users")) {
5197 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5198 cur_arg += 2;
5199 continue;
5200 } else {
5201 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5202 file, linenum, args[0]);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206 }
5207
5208 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5209 } else if (!strcmp(args[0], "user")) { /* new user */
5210 struct auth_users *newuser;
5211 int cur_arg;
5212
5213 if (!*args[1]) {
5214 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5215 file, linenum, args[0]);
5216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219
5220 for (newuser = userlist->users; newuser; newuser = newuser->next)
5221 if (!strcmp(newuser->user, args[1])) {
5222 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5223 file, linenum, args[1], userlist->name);
5224 err_code |= ERR_ALERT;
5225 goto out;
5226 }
5227
5228 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5229 if (!newuser) {
5230 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5231 err_code |= ERR_ALERT | ERR_ABORT;
5232 goto out;
5233 }
5234
5235 newuser->user = strdup(args[1]);
5236
5237 newuser->next = userlist->users;
5238 userlist->users = newuser;
5239
5240 cur_arg = 2;
5241
5242 while (*args[cur_arg]) {
5243 if (!strcmp(args[cur_arg], "password")) {
5244#ifndef CONFIG_HAP_CRYPT
5245 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5246 file, linenum);
5247 err_code |= ERR_ALERT;
5248#endif
5249 newuser->pass = strdup(args[cur_arg + 1]);
5250 cur_arg += 2;
5251 continue;
5252 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5253 newuser->pass = strdup(args[cur_arg + 1]);
5254 newuser->flags |= AU_O_INSECURE;
5255 cur_arg += 2;
5256 continue;
5257 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005258 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005259 cur_arg += 2;
5260 continue;
5261 } else {
5262 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5263 file, linenum, args[0]);
5264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
5266 }
5267 }
5268 } else {
5269 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 }
5272
5273out:
5274 return err_code;
5275}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276
5277/*
5278 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005279 * Returns the error code, 0 if OK, or any combination of :
5280 * - ERR_ABORT: must abort ASAP
5281 * - ERR_FATAL: we can continue parsing but not start the service
5282 * - ERR_WARN: a warning has been emitted
5283 * - ERR_ALERT: an alert has been emitted
5284 * Only the two first ones can stop processing, the two others are just
5285 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005287int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005289 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005290 FILE *f;
5291 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005293 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 if ((f=fopen(file,"r")) == NULL)
5296 return -1;
5297
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005298 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005299 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005300 char *end;
5301 char *args[MAX_LINE_ARGS + 1];
5302 char *line = thisline;
5303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 linenum++;
5305
5306 end = line + strlen(line);
5307
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005308 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5309 /* Check if we reached the limit and the last char is not \n.
5310 * Watch out for the last line without the terminating '\n'!
5311 */
5312 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005313 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005314 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005315 }
5316
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005318 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005319 line++;
5320
5321 arg = 0;
5322 args[arg] = line;
5323
5324 while (*line && arg < MAX_LINE_ARGS) {
5325 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5326 * C equivalent value. Other combinations left unchanged (eg: \1).
5327 */
5328 if (*line == '\\') {
5329 int skip = 0;
5330 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5331 *line = line[1];
5332 skip = 1;
5333 }
5334 else if (line[1] == 'r') {
5335 *line = '\r';
5336 skip = 1;
5337 }
5338 else if (line[1] == 'n') {
5339 *line = '\n';
5340 skip = 1;
5341 }
5342 else if (line[1] == 't') {
5343 *line = '\t';
5344 skip = 1;
5345 }
5346 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005347 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 unsigned char hex1, hex2;
5349 hex1 = toupper(line[2]) - '0';
5350 hex2 = toupper(line[3]) - '0';
5351 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5352 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5353 *line = (hex1<<4) + hex2;
5354 skip = 3;
5355 }
5356 else {
5357 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 }
5360 }
5361 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005362 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 end -= skip;
5364 }
5365 line++;
5366 }
5367 else if (*line == '#' || *line == '\n' || *line == '\r') {
5368 /* end of string, end of loop */
5369 *line = 0;
5370 break;
5371 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005372 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005374 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005375 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 line++;
5377 args[++arg] = line;
5378 }
5379 else {
5380 line++;
5381 }
5382 }
5383
5384 /* empty line */
5385 if (!**args)
5386 continue;
5387
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005388 if (*line) {
5389 /* we had to stop due to too many args.
5390 * Let's terminate the string, print the offending part then cut the
5391 * last arg.
5392 */
5393 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5394 line++;
5395 *line = '\0';
5396
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005397 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005398 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 args[arg] = line;
5401 }
5402
Willy Tarreau540abe42007-05-02 20:50:16 +02005403 /* zero out remaining args and ensure that at least one entry
5404 * is zeroed out.
5405 */
5406 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005407 args[arg] = line;
5408 }
5409
Willy Tarreau3842f002009-06-14 11:39:52 +02005410 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005411 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005412 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005413 for (arg=0; *args[arg+1]; arg++)
5414 args[arg] = args[arg+1]; // shift args after inversion
5415 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005416 else if (!strcmp(args[0], "default")) {
5417 kwm = KWM_DEF;
5418 for (arg=0; *args[arg+1]; arg++)
5419 args[arg] = args[arg+1]; // shift args after inversion
5420 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005421
Willy Tarreau3842f002009-06-14 11:39:52 +02005422 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5423 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005424 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005425 }
5426
Willy Tarreau977b8e42006-12-29 14:19:17 +01005427 if (!strcmp(args[0], "listen") ||
5428 !strcmp(args[0], "frontend") ||
5429 !strcmp(args[0], "backend") ||
5430 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005431 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005432 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005433 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005434 cursection = strdup(args[0]);
5435 }
5436 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005438 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005439 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005440 }
5441 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005442 confsect = CFG_USERLIST;
5443 free(cursection);
5444 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005445 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005446 else if (!strcmp(args[0], "peers")) {
5447 confsect = CFG_PEERS;
5448 free(cursection);
5449 cursection = strdup(args[0]);
5450 }
5451
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 /* else it's a section keyword */
5453
5454 switch (confsect) {
5455 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 break;
5458 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005459 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005461 case CFG_USERLIST:
5462 err_code |= cfg_parse_users(file, linenum, args, kwm);
5463 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005464 case CFG_PEERS:
5465 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5466 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005468 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005471
5472 if (err_code & ERR_ABORT)
5473 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005475 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005476 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005478 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005479}
5480
Willy Tarreaubb925012009-07-23 13:36:36 +02005481/*
5482 * Returns the error code, 0 if OK, or any combination of :
5483 * - ERR_ABORT: must abort ASAP
5484 * - ERR_FATAL: we can continue parsing but not start the service
5485 * - ERR_WARN: a warning has been emitted
5486 * - ERR_ALERT: an alert has been emitted
5487 * Only the two first ones can stop processing, the two others are just
5488 * indicators.
5489 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005490int check_config_validity()
5491{
5492 int cfgerr = 0;
5493 struct proxy *curproxy = NULL;
5494 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005495 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005496 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005497 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498
5499 /*
5500 * Now, check for the integrity of all that we have collected.
5501 */
5502
5503 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005504 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005506 /* first, we will invert the proxy list order */
5507 curproxy = NULL;
5508 while (proxy) {
5509 struct proxy *next;
5510
5511 next = proxy->next;
5512 proxy->next = curproxy;
5513 curproxy = proxy;
5514 if (!next)
5515 break;
5516 proxy = next;
5517 }
5518
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005520 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524
5525 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005526 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005527 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005528 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005529 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005530 unsigned int next_id;
5531
5532 if (!curproxy->uuid) {
5533 /* proxy ID not set, use automatic numbering with first
5534 * spare entry starting with next_pxid.
5535 */
5536 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5537 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5538 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005539 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005540 next_pxid++;
5541
Willy Tarreau55ea7572007-06-17 19:56:27 +02005542
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005544 /* ensure we don't keep listeners uselessly bound */
5545 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 curproxy = curproxy->next;
5547 continue;
5548 }
5549
Willy Tarreauff01a212009-03-15 13:46:16 +01005550 switch (curproxy->mode) {
5551 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005552 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005553 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005554 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5555 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005556 cfgerr++;
5557 }
5558
5559 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005560 Warning("config : servers will be ignored for %s '%s'.\n",
5561 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005562 break;
5563
5564 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005565 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005566 break;
5567
5568 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005569 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005570 break;
5571 }
5572
5573 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005574 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5575 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 cfgerr++;
5577 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005578
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005579 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005580 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005581 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005582 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5583 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005584 cfgerr++;
5585 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005587 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005588 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5589 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005590 cfgerr++;
5591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005593 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5595 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005596 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 }
5598 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005599 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 /* If no LB algo is set in a backend, and we're not in
5601 * transparent mode, dispatch mode nor proxy mode, we
5602 * want to use balance roundrobin by default.
5603 */
5604 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5605 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 }
5607 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005608
Willy Tarreau1620ec32011-08-06 17:05:02 +02005609 if (curproxy->options & PR_O_DISPATCH)
5610 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5611 else if (curproxy->options & PR_O_HTTP_PROXY)
5612 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5613 else if (curproxy->options & PR_O_TRANSP)
5614 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005615
Willy Tarreau1620ec32011-08-06 17:05:02 +02005616 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5617 if (curproxy->options & PR_O_DISABLE404) {
5618 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5619 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5620 err_code |= ERR_WARN;
5621 curproxy->options &= ~PR_O_DISABLE404;
5622 }
5623 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5624 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5625 "send-state", proxy_type_str(curproxy), curproxy->id);
5626 err_code |= ERR_WARN;
5627 curproxy->options &= ~PR_O2_CHK_SNDST;
5628 }
Willy Tarreauef781042010-01-27 11:53:01 +01005629 }
5630
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005631 /* if a default backend was specified, let's find it */
5632 if (curproxy->defbe.name) {
5633 struct proxy *target;
5634
Alex Williams96532db2009-11-01 21:27:13 -05005635 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005636 if (!target) {
5637 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5638 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005639 cfgerr++;
5640 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005641 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5642 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005643 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005644 } else {
5645 free(curproxy->defbe.name);
5646 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005647 /* we force the backend to be present on at least all of
5648 * the frontend's processes.
5649 */
5650 target->bind_proc = curproxy->bind_proc ?
5651 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
5653 }
5654
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005655 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005656 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5657 /* map jump target for ACT_SETBE in req_rep chain */
5658 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005659 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005660 struct proxy *target;
5661
Willy Tarreaua496b602006-12-17 23:15:24 +01005662 if (exp->action != ACT_SETBE)
5663 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005664
Alex Williams96532db2009-11-01 21:27:13 -05005665 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005666 if (!target) {
5667 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5668 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005669 cfgerr++;
5670 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005671 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5672 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005673 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005674 } else {
5675 free((void *)exp->replace);
5676 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005677 /* we force the backend to be present on at least all of
5678 * the frontend's processes.
5679 */
5680 target->bind_proc = curproxy->bind_proc ?
5681 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005682 }
5683 }
5684 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005685
5686 /* find the target proxy for 'use_backend' rules */
5687 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005688 struct proxy *target;
5689
Alex Williams96532db2009-11-01 21:27:13 -05005690 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005691
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005692 if (!target) {
5693 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5694 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005695 cfgerr++;
5696 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005697 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5698 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005699 cfgerr++;
5700 } else {
5701 free((void *)rule->be.name);
5702 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005703 /* we force the backend to be present on at least all of
5704 * the frontend's processes.
5705 */
5706 target->bind_proc = curproxy->bind_proc ?
5707 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708 }
5709 }
5710
Emeric Brunb982a3d2010-01-04 15:45:53 +01005711 /* find the target table for 'stick' rules */
5712 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5713 struct proxy *target;
5714
Emeric Brun1d33b292010-01-04 15:47:17 +01005715 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5716 if (mrule->flags & STK_IS_STORE)
5717 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5718
Emeric Brunb982a3d2010-01-04 15:45:53 +01005719 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005720 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005721 else
5722 target = curproxy;
5723
5724 if (!target) {
5725 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5726 curproxy->id, mrule->table.name);
5727 cfgerr++;
5728 }
5729 else if (target->table.size == 0) {
5730 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5731 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5732 cfgerr++;
5733 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005734 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005735 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5736 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5737 cfgerr++;
5738 }
5739 else {
5740 free((void *)mrule->table.name);
5741 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005742 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005743 }
5744 }
5745
5746 /* find the target table for 'store response' rules */
5747 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5748 struct proxy *target;
5749
Emeric Brun1d33b292010-01-04 15:47:17 +01005750 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5751
Emeric Brunb982a3d2010-01-04 15:45:53 +01005752 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005753 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005754 else
5755 target = curproxy;
5756
5757 if (!target) {
5758 Alert("Proxy '%s': unable to find store table '%s'.\n",
5759 curproxy->id, mrule->table.name);
5760 cfgerr++;
5761 }
5762 else if (target->table.size == 0) {
5763 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5764 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5765 cfgerr++;
5766 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005767 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005768 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5769 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5770 cfgerr++;
5771 }
5772 else {
5773 free((void *)mrule->table.name);
5774 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005775 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005776 }
5777 }
5778
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005779 /* find the target table for 'tcp-request' layer 4 rules */
5780 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5781 struct proxy *target;
5782
Willy Tarreau56123282010-08-06 19:06:56 +02005783 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005784 continue;
5785
5786 if (trule->act_prm.trk_ctr.table.n)
5787 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5788 else
5789 target = curproxy;
5790
5791 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005792 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5793 curproxy->id, trule->act_prm.trk_ctr.table.n,
5794 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005795 cfgerr++;
5796 }
5797 else if (target->table.size == 0) {
5798 Alert("Proxy '%s': table '%s' used but not configured.\n",
5799 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5800 cfgerr++;
5801 }
5802 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005803 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 +02005804 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5805 cfgerr++;
5806 }
5807 else {
5808 free(trule->act_prm.trk_ctr.table.n);
5809 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005810 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005811 * to pass a list of counters to track and allocate them right here using
5812 * stktable_alloc_data_type().
5813 */
5814 }
5815 }
5816
Willy Tarreaud1f96522010-08-03 19:34:32 +02005817 /* find the target table for 'tcp-request' layer 6 rules */
5818 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5819 struct proxy *target;
5820
Willy Tarreau56123282010-08-06 19:06:56 +02005821 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005822 continue;
5823
5824 if (trule->act_prm.trk_ctr.table.n)
5825 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5826 else
5827 target = curproxy;
5828
5829 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005830 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5831 curproxy->id, trule->act_prm.trk_ctr.table.n,
5832 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005833 cfgerr++;
5834 }
5835 else if (target->table.size == 0) {
5836 Alert("Proxy '%s': table '%s' used but not configured.\n",
5837 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5838 cfgerr++;
5839 }
5840 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005841 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 +02005842 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5843 cfgerr++;
5844 }
5845 else {
5846 free(trule->act_prm.trk_ctr.table.n);
5847 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005848 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005849 * to pass a list of counters to track and allocate them right here using
5850 * stktable_alloc_data_type().
5851 */
5852 }
5853 }
5854
Emeric Brun32da3c42010-09-23 18:39:19 +02005855 if (curproxy->table.peers.name) {
5856 struct peers *curpeers = peers;
5857
5858 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5859 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5860 free((void *)curproxy->table.peers.name);
5861 curproxy->table.peers.p = peers;
5862 break;
5863 }
5864 }
5865
5866 if (!curpeers) {
5867 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5868 curproxy->id, curproxy->table.peers.name);
5869 cfgerr++;
5870 }
5871 else if (!curpeers->peers_fe) {
5872 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5873 curproxy->id, curpeers->id);
5874 cfgerr++;
5875 }
5876 }
5877
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005878 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005879 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005880 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5881 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5882 "proxy", curproxy->id);
5883 cfgerr++;
5884 goto out_uri_auth_compat;
5885 }
5886
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005887 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005888 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005889 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005890 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005891
Willy Tarreau95fa4692010-02-01 13:05:50 +01005892 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5893 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005894
5895 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005896 uri_auth_compat_req[i++] = "realm";
5897 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5898 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005899
Willy Tarreau95fa4692010-02-01 13:05:50 +01005900 uri_auth_compat_req[i++] = "unless";
5901 uri_auth_compat_req[i++] = "{";
5902 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5903 uri_auth_compat_req[i++] = "}";
5904 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005905
Willy Tarreauff011f22011-01-06 17:51:27 +01005906 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5907 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005908 cfgerr++;
5909 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005910 }
5911
Willy Tarreauff011f22011-01-06 17:51:27 +01005912 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005913
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914 if (curproxy->uri_auth->auth_realm) {
5915 free(curproxy->uri_auth->auth_realm);
5916 curproxy->uri_auth->auth_realm = NULL;
5917 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005918
5919 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005920 }
5921out_uri_auth_compat:
5922
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005923 cfgerr += acl_find_targets(curproxy);
5924
Willy Tarreau2738a142006-07-08 17:28:09 +02005925 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005926 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005927 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005928 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005929 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005930 " | While not properly invalid, you will certainly encounter various problems\n"
5931 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005932 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005933 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005934 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005935 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005936
Willy Tarreau1fa31262007-12-03 00:36:16 +01005937 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5938 * We must still support older configurations, so let's find out whether those
5939 * parameters have been set or must be copied from contimeouts.
5940 */
5941 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005942 if (!curproxy->timeout.tarpit ||
5943 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005944 /* tarpit timeout not set. We search in the following order:
5945 * default.tarpit, curr.connect, default.connect.
5946 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005947 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005948 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005949 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005950 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005951 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005952 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005953 }
5954 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005955 (!curproxy->timeout.queue ||
5956 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005957 /* queue timeout not set. We search in the following order:
5958 * default.queue, curr.connect, default.connect.
5959 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005960 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005961 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005962 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005963 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005964 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005965 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005966 }
5967 }
5968
Willy Tarreau1620ec32011-08-06 17:05:02 +02005969 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005970 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5971 curproxy->check_req = (char *)malloc(curproxy->check_len);
5972 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005973 }
5974
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005975 /* The small pools required for the capture lists */
5976 if (curproxy->nb_req_cap)
5977 curproxy->req_cap_pool = create_pool("ptrcap",
5978 curproxy->nb_req_cap * sizeof(char *),
5979 MEM_F_SHARED);
5980 if (curproxy->nb_rsp_cap)
5981 curproxy->rsp_cap_pool = create_pool("ptrcap",
5982 curproxy->nb_rsp_cap * sizeof(char *),
5983 MEM_F_SHARED);
5984
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005985 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5986 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5987 MEM_F_SHARED);
5988
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 /* first, we will invert the servers list order */
5990 newsrv = NULL;
5991 while (curproxy->srv) {
5992 struct server *next;
5993
5994 next = curproxy->srv->next;
5995 curproxy->srv->next = newsrv;
5996 newsrv = curproxy->srv;
5997 if (!next)
5998 break;
5999 curproxy->srv = next;
6000 }
6001
Willy Tarreaudd701652010-05-25 23:03:02 +02006002 /* assign automatic UIDs to servers which don't have one yet */
6003 next_id = 1;
6004 newsrv = curproxy->srv;
6005 while (newsrv != NULL) {
6006 if (!newsrv->puid) {
6007 /* server ID not set, use automatic numbering with first
6008 * spare entry starting with next_svid.
6009 */
6010 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6011 newsrv->conf.id.key = newsrv->puid = next_id;
6012 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6013 }
6014 next_id++;
6015 newsrv = newsrv->next;
6016 }
6017
Willy Tarreau20697042007-11-15 23:26:18 +01006018 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006019 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006021 /* We have to initialize the server lookup mechanism depending
6022 * on what LB algorithm was choosen.
6023 */
6024
6025 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6026 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6027 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006028 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6029 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6030 init_server_map(curproxy);
6031 } else {
6032 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6033 fwrr_init_server_groups(curproxy);
6034 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006035 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006036
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006037 case BE_LB_KIND_LC:
6038 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006039 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006040 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006041
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006042 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006043 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6044 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6045 chash_init_server_tree(curproxy);
6046 } else {
6047 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6048 init_server_map(curproxy);
6049 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006050 break;
6051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006052
6053 if (curproxy->options & PR_O_LOGASAP)
6054 curproxy->to_log &= ~LW_BYTES;
6055
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006056 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6057 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6058 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6059 proxy_type_str(curproxy), curproxy->id);
6060 err_code |= ERR_WARN;
6061 }
6062
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006063 if (curproxy->mode != PR_MODE_HTTP) {
6064 int optnum;
6065
6066 if (curproxy->options & PR_O_COOK_ANY) {
6067 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6068 proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
6070 }
6071
6072 if (curproxy->uri_auth) {
6073 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6074 proxy_type_str(curproxy), curproxy->id);
6075 err_code |= ERR_WARN;
6076 curproxy->uri_auth = NULL;
6077 }
6078
Willy Tarreau87cf5142011-08-19 22:57:24 +02006079 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006080 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6081 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6082 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006083 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006084 }
6085
6086 if (curproxy->options & PR_O_ORGTO) {
6087 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6088 "originalto", proxy_type_str(curproxy), curproxy->id);
6089 err_code |= ERR_WARN;
6090 curproxy->options &= ~PR_O_ORGTO;
6091 }
6092
6093 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6094 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6095 (curproxy->cap & cfg_opts[optnum].cap) &&
6096 (curproxy->options & cfg_opts[optnum].val)) {
6097 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6098 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6099 err_code |= ERR_WARN;
6100 curproxy->options &= ~cfg_opts[optnum].val;
6101 }
6102 }
6103
6104 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6105 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6106 (curproxy->cap & cfg_opts2[optnum].cap) &&
6107 (curproxy->options2 & cfg_opts2[optnum].val)) {
6108 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6109 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6110 err_code |= ERR_WARN;
6111 curproxy->options2 &= ~cfg_opts2[optnum].val;
6112 }
6113 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006114
Willy Tarreauefa5f512010-03-30 20:13:29 +02006115#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006116 if (curproxy->bind_hdr_occ) {
6117 curproxy->bind_hdr_occ = 0;
6118 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6119 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6120 err_code |= ERR_WARN;
6121 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006122#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006123 }
6124
Willy Tarreaubaaee002006-06-26 02:48:02 +02006125 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006126 * ensure that we're not cross-dressing a TCP server into HTTP.
6127 */
6128 newsrv = curproxy->srv;
6129 while (newsrv != NULL) {
6130 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006131 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6132 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006133 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006134 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006135
Willy Tarreauefa5f512010-03-30 20:13:29 +02006136#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006137 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6138 newsrv->bind_hdr_occ = 0;
6139 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6140 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6141 err_code |= ERR_WARN;
6142 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006143#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006144 newsrv = newsrv->next;
6145 }
6146
6147 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 * If this server supports a maxconn parameter, it needs a dedicated
6149 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006150 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006151 */
6152 newsrv = curproxy->srv;
6153 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006154 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155 /* Only 'minconn' was specified, or it was higher than or equal
6156 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6157 * this will avoid further useless expensive computations.
6158 */
6159 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006160 } else if (newsrv->maxconn && !newsrv->minconn) {
6161 /* minconn was not specified, so we set it to maxconn */
6162 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 }
6164
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006165 if (newsrv->trackit) {
6166 struct proxy *px;
6167 struct server *srv;
6168 char *pname, *sname;
6169
6170 pname = newsrv->trackit;
6171 sname = strrchr(pname, '/');
6172
6173 if (sname)
6174 *sname++ = '\0';
6175 else {
6176 sname = pname;
6177 pname = NULL;
6178 }
6179
6180 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006181 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006182 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006183 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6184 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006185 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006186 cfgerr++;
6187 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006188 }
6189 } else
6190 px = curproxy;
6191
6192 srv = findserver(px, sname);
6193 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006194 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6195 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006196 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006197 cfgerr++;
6198 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006199 }
6200
6201 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006202 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006203 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006204 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006206 cfgerr++;
6207 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006208 }
6209
6210 if (curproxy != px &&
6211 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006212 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006213 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006214 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006215 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006216 cfgerr++;
6217 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006218 }
6219
6220 newsrv->tracked = srv;
6221 newsrv->tracknext = srv->tracknext;
6222 srv->tracknext = newsrv;
6223
6224 free(newsrv->trackit);
6225 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006226 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006227 newsrv = newsrv->next;
6228 }
6229
Willy Tarreauc1a21672009-08-16 22:37:44 +02006230 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006231 curproxy->accept = frontend_accept;
6232
Willy Tarreauc1a21672009-08-16 22:37:44 +02006233 if (curproxy->tcp_req.inspect_delay ||
6234 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006235 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006236
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006237 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006238 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006239 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006240 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006241
6242 /* both TCP and HTTP must check switching rules */
6243 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6244 }
6245
6246 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006247 if (curproxy->tcp_req.inspect_delay ||
6248 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6249 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6250
Emeric Brun97679e72010-09-23 17:56:44 +02006251 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6252 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6253
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006254 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006255 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006256 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006257 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006258
6259 /* If the backend does requires RDP cookie persistence, we have to
6260 * enable the corresponding analyser.
6261 */
6262 if (curproxy->options2 & PR_O2_RDPC_PRST)
6263 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6264 }
6265
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006266 listener = NULL;
6267 while (curproxy->listen) {
6268 struct listener *next;
6269
6270 next = curproxy->listen->next;
6271 curproxy->listen->next = listener;
6272 listener = curproxy->listen;
6273
6274 if (!next)
6275 break;
6276
6277 curproxy->listen = next;
6278 }
6279
Willy Tarreaue6b98942007-10-29 01:09:36 +01006280 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006281 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006282 listener = curproxy->listen;
6283 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006284 if (!listener->luid) {
6285 /* listener ID not set, use automatic numbering with first
6286 * spare entry starting with next_luid.
6287 */
6288 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6289 listener->conf.id.key = listener->luid = next_id;
6290 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006291 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006292 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006293
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006294 /* enable separate counters */
6295 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6296 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6297 if (!listener->name) {
6298 sprintf(trash, "sock-%d", listener->luid);
6299 listener->name = strdup(trash);
6300 }
6301 }
6302
Willy Tarreaue6b98942007-10-29 01:09:36 +01006303 if (curproxy->options & PR_O_TCP_NOLING)
6304 listener->options |= LI_O_NOLINGER;
6305 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006306 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006307 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006308 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006309 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006310 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006311 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006312
Willy Tarreau8a956912010-10-15 14:27:08 +02006313 if (listener->options & LI_O_ACC_PROXY)
6314 listener->analysers |= AN_REQ_DECODE_PROXY;
6315
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006316 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6317 listener->options |= LI_O_TCP_RULES;
6318
Willy Tarreaude3041d2010-05-31 10:56:17 +02006319 if (curproxy->mon_mask.s_addr)
6320 listener->options |= LI_O_CHK_MONNET;
6321
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006322 /* smart accept mode is automatic in HTTP mode */
6323 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6324 (curproxy->mode == PR_MODE_HTTP &&
6325 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6326 listener->options |= LI_O_NOQUICKACK;
6327
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006328 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006329 listener = listener->next;
6330 }
6331
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006332 /* Check multi-process mode compatibility for the current proxy */
6333 if (global.nbproc > 1) {
6334 int nbproc = 0;
6335 if (curproxy->bind_proc) {
6336 int proc;
6337 for (proc = 0; proc < global.nbproc; proc++) {
6338 if (curproxy->bind_proc & (1 << proc)) {
6339 nbproc++;
6340 }
6341 }
6342 } else {
6343 nbproc = global.nbproc;
6344 }
6345 if (curproxy->table.peers.name) {
6346 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6347 curproxy->id);
6348 cfgerr++;
6349 }
6350 if (nbproc > 1) {
6351 if (curproxy->uri_auth) {
6352 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6353 curproxy->id);
6354 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6355 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6356 curproxy->id);
6357 }
6358 }
6359 if (curproxy->appsession_name) {
6360 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6361 curproxy->id);
6362 }
6363 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6364 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6365 curproxy->id);
6366 }
6367 }
6368 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006369
6370 /* create the task associated with the proxy */
6371 curproxy->task = task_new();
6372 if (curproxy->task) {
6373 curproxy->task->context = curproxy;
6374 curproxy->task->process = manage_proxy;
6375 /* no need to queue, it will be done automatically if some
6376 * listener gets limited.
6377 */
6378 curproxy->task->expire = TICK_ETERNITY;
6379 } else {
6380 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6381 curproxy->id);
6382 cfgerr++;
6383 }
6384
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 curproxy = curproxy->next;
6386 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006387
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006388 /* Check multi-process mode compatibility */
6389 if (global.nbproc > 1) {
6390 if (global.stats_fe) {
6391 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6392 }
6393 }
6394
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006395 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6396 struct auth_users *curuser;
6397 int g;
6398
6399 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6400 unsigned int group_mask = 0;
6401 char *group = NULL;
6402
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006403 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006404 continue;
6405
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006406 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006407
6408 for (g = 0; g < curuserlist->grpcnt; g++)
6409 if (!strcmp(curuserlist->groups[g], group))
6410 break;
6411
6412 if (g == curuserlist->grpcnt) {
6413 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6414 curuserlist->name, group, curuser->user);
6415 err_code |= ERR_ALERT | ERR_FATAL;
6416 goto out;
6417 }
6418
6419 group_mask |= (1 << g);
6420 }
6421
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006422 free(curuser->u.groups);
6423 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006424 }
6425
6426 for (g = 0; g < curuserlist->grpcnt; g++) {
6427 char *user = NULL;
6428
6429 if (!curuserlist->groupusers[g])
6430 continue;
6431
6432 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6433 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6434 if (!strcmp(curuser->user, user))
6435 break;
6436
6437 if (!curuser) {
6438 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6439 curuserlist->name, user, curuserlist->groups[g]);
6440 err_code |= ERR_ALERT | ERR_FATAL;
6441 goto out;
6442 }
6443
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006444 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006445 }
6446
6447 free(curuserlist->groupusers[g]);
6448 }
6449
6450 free(curuserlist->groupusers);
6451
6452#ifdef DEBUG_AUTH
6453 for (g = 0; g < curuserlist->grpcnt; g++) {
6454 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6455
6456 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6457 if (curuser->group_mask & (1 << g))
6458 fprintf(stderr, " %s", curuser->user);
6459 }
6460
6461 fprintf(stderr, "\n");
6462 }
6463#endif
6464
Willy Tarreaufbb78422011-06-05 15:38:35 +02006465 }
6466
6467 /* automatically compute fullconn if not set. We must not do it in the
6468 * loop above because cross-references are not yet fully resolved.
6469 */
6470 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6471 /* If <fullconn> is not set, let's set it to 10% of the sum of
6472 * the possible incoming frontend's maxconns.
6473 */
6474 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6475 struct proxy *fe;
6476 int total = 0;
6477
6478 /* sum up the number of maxconns of frontends which
6479 * reference this backend at least once or which are
6480 * the same one ('listen').
6481 */
6482 for (fe = proxy; fe; fe = fe->next) {
6483 struct switching_rule *rule;
6484 struct hdr_exp *exp;
6485 int found = 0;
6486
6487 if (!(fe->cap & PR_CAP_FE))
6488 continue;
6489
6490 if (fe == curproxy) /* we're on a "listen" instance */
6491 found = 1;
6492
6493 if (fe->defbe.be == curproxy) /* "default_backend" */
6494 found = 1;
6495
6496 /* check if a "use_backend" rule matches */
6497 if (!found) {
6498 list_for_each_entry(rule, &fe->switching_rules, list) {
6499 if (rule->be.backend == curproxy) {
6500 found = 1;
6501 break;
6502 }
6503 }
6504 }
6505
6506 /* check if a "reqsetbe" rule matches */
6507 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6508 if (exp->action == ACT_SETBE &&
6509 (struct proxy *)exp->replace == curproxy) {
6510 found = 1;
6511 break;
6512 }
6513 }
6514
6515 /* now we've checked all possible ways to reference a backend
6516 * from a frontend.
6517 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006518 if (!found)
6519 continue;
6520 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006521 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006522 /* we have the sum of the maxconns in <total>. We only
6523 * keep 10% of that sum to set the default fullconn, with
6524 * a hard minimum of 1 (to avoid a divide by zero).
6525 */
6526 curproxy->fullconn = (total + 9) / 10;
6527 if (!curproxy->fullconn)
6528 curproxy->fullconn = 1;
6529 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006530 }
6531
Willy Tarreau056f5682010-06-06 15:51:11 +02006532 /* initialize stick-tables on backend capable proxies. This must not
6533 * be done earlier because the data size may be discovered while parsing
6534 * other proxies.
6535 */
6536 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006537 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006538
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006539 /*
6540 * Recount currently required checks.
6541 */
6542
6543 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6544 int optnum;
6545
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006546 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6547 if (curproxy->options & cfg_opts[optnum].val)
6548 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006549
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006550 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6551 if (curproxy->options2 & cfg_opts2[optnum].val)
6552 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006553 }
6554
Willy Tarreaubb925012009-07-23 13:36:36 +02006555 if (cfgerr > 0)
6556 err_code |= ERR_ALERT | ERR_FATAL;
6557 out:
6558 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006559}
6560
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006561/*
6562 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6563 * parsing sessions.
6564 */
6565void cfg_register_keywords(struct cfg_kw_list *kwl)
6566{
6567 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6568}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006570/*
6571 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6572 */
6573void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6574{
6575 LIST_DEL(&kwl->list);
6576 LIST_INIT(&kwl->list);
6577}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578
6579/*
6580 * Local variables:
6581 * c-indent-level: 8
6582 * c-basic-offset: 8
6583 * End:
6584 */