blob: f6a0ef2fe6ff002a2e3e2b822514b88cb0a3089e [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001023void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001025 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 defproxy.mode = PR_MODE_TCP;
1027 defproxy.state = PR_STNEW;
1028 defproxy.maxconn = cfg_maxpconn;
1029 defproxy.conn_retries = CONN_RETRIES;
1030 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001031
1032 defproxy.defsrv.inter = DEF_CHKINTR;
1033 defproxy.defsrv.fastinter = 0;
1034 defproxy.defsrv.downinter = 0;
1035 defproxy.defsrv.rise = DEF_RISETIME;
1036 defproxy.defsrv.fall = DEF_FALLTIME;
1037 defproxy.defsrv.check_port = 0;
1038 defproxy.defsrv.maxqueue = 0;
1039 defproxy.defsrv.minconn = 0;
1040 defproxy.defsrv.maxconn = 0;
1041 defproxy.defsrv.slowstart = 0;
1042 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1043 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1044 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045}
1046
Willy Tarreauade5ec42010-01-28 19:33:49 +01001047
1048static int create_cond_regex_rule(const char *file, int line,
1049 struct proxy *px, int dir, int action, int flags,
1050 const char *cmd, const char *reg, const char *repl,
1051 const char **cond_start)
1052{
1053 regex_t *preg = NULL;
1054 const char *err;
1055 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001056 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001057
1058 if (px == &defproxy) {
1059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto err;
1062 }
1063
1064 if (*reg == 0) {
1065 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto err;
1068 }
1069
1070 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1071 err_code |= ERR_WARN;
1072
Willy Tarreau5321c422010-01-28 20:35:13 +01001073 if (cond_start &&
1074 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1075 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1076 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1077 file, line, cmd);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto err;
1080 }
1081 }
1082 else if (cond_start && **cond_start) {
1083 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1084 file, line, cmd, *cond_start);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto err;
1087 }
1088
1089 if (dir == ACL_DIR_REQ)
1090 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001091 else
1092 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001093
Willy Tarreauade5ec42010-01-28 19:33:49 +01001094 preg = calloc(1, sizeof(regex_t));
1095 if (!preg) {
1096 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1097 err_code = ERR_ALERT | ERR_FATAL;
1098 goto err;
1099 }
1100
1101 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1102 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1103 err_code = ERR_ALERT | ERR_FATAL;
1104 goto err;
1105 }
1106
1107 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001108 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001109 if (repl && err) {
1110 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1111 file, line, cmd, *err);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1117 err_code |= ERR_WARN;
1118
1119 return err_code;
1120 err:
1121 free(preg);
1122 return err_code;
1123}
1124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001126 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001127 * Returns the error code, 0 if OK, or any combination of :
1128 * - ERR_ABORT: must abort ASAP
1129 * - ERR_FATAL: we can continue parsing but not start the service
1130 * - ERR_WARN: a warning has been emitted
1131 * - ERR_ALERT: an alert has been emitted
1132 * Only the two first ones can stop processing, the two others are just
1133 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001135int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1136{
1137 static struct peers *curpeers = NULL;
1138 struct peer *newpeer = NULL;
1139 const char *err;
1140 int err_code = 0;
1141
1142 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1143
1144 err = invalid_char(args[1]);
1145 if (err) {
1146 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1147 file, linenum, *err, args[0], args[1]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 }
1150
1151 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1152 /*
1153 * If there are two proxies with the same name only following
1154 * combinations are allowed:
1155 */
1156 if (strcmp(curpeers->id, args[1]) == 0) {
1157 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1158 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1159 err_code |= ERR_WARN;
1160 }
1161 }
1162
1163 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1164 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1165 err_code |= ERR_ALERT | ERR_ABORT;
1166 goto out;
1167 }
1168
1169 curpeers->next = peers;
1170 peers = curpeers;
1171 curpeers->conf.file = file;
1172 curpeers->conf.line = linenum;
1173 curpeers->last_change = now.tv_sec;
1174 curpeers->id = strdup(args[1]);
1175 }
1176 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1177 char *rport, *raddr;
1178 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001179 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001180
1181 if (!*args[2]) {
1182 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 err = invalid_char(args[1]);
1189 if (err) {
1190 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1191 file, linenum, *err, args[1]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
1195
1196 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1198 err_code |= ERR_ALERT | ERR_ABORT;
1199 goto out;
1200 }
1201
1202 /* the peers are linked backwards first */
1203 curpeers->count++;
1204 newpeer->next = curpeers->remote;
1205 curpeers->remote = newpeer;
1206 newpeer->peers = curpeers;
1207 newpeer->conf.file = file;
1208 newpeer->conf.line = linenum;
1209
1210 newpeer->last_change = now.tv_sec;
1211 newpeer->id = strdup(args[1]);
1212
1213 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001214 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001215 if (rport) {
1216 *rport++ = 0;
1217 realport = atol(rport);
1218 }
1219 if (!realport) {
1220 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
Willy Tarreaufab5a432011-03-04 15:31:53 +01001225 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001226 free(raddr);
1227 if (!sk) {
1228 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001233
1234 switch (newpeer->addr.ss_family) {
1235 case AF_INET:
1236 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1237 break;
1238 case AF_INET6:
1239 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1240 break;
1241 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001242
1243 if (strcmp(newpeer->id, localpeer) == 0) {
1244 /* Current is local peer, it define a frontend */
1245 newpeer->local = 1;
1246
1247 if (!curpeers->peers_fe) {
1248 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1249 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1250 err_code |= ERR_ALERT | ERR_ABORT;
1251 goto out;
1252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001253
Willy Tarreau237250c2011-07-29 01:49:03 +02001254 init_new_proxy(curpeers->peers_fe);
1255 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001256
1257 curpeers->peers_fe->last_change = now.tv_sec;
1258 curpeers->peers_fe->id = strdup(args[1]);
1259 curpeers->peers_fe->cap = PR_CAP_FE;
1260 curpeers->peers_fe->maxconn = 65000;
1261 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1262 curpeers->peers_fe->timeout.connect = 5000;
1263 curpeers->peers_fe->accept = peer_accept;
1264 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001265 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001266 err_code |= ERR_FATAL;
1267 goto out;
1268 }
1269 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1270 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1271 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1272 curpeers->peers_fe->listen->accept = session_accept;
1273 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1274 curpeers->peers_fe->listen->handler = process_session;
1275 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1276 }
1277 }
1278 } /* neither "peer" nor "peers" */
1279 else if (*args[0] != 0) {
1280 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284
1285out:
1286 return err_code;
1287}
1288
1289
Willy Tarreau3842f002009-06-14 11:39:52 +02001290int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291{
1292 static struct proxy *curproxy = NULL;
1293 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001294 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001295 int rc;
1296 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001297 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001298 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001299
Willy Tarreau977b8e42006-12-29 14:19:17 +01001300 if (!strcmp(args[0], "listen"))
1301 rc = PR_CAP_LISTEN;
1302 else if (!strcmp(args[0], "frontend"))
1303 rc = PR_CAP_FE | PR_CAP_RS;
1304 else if (!strcmp(args[0], "backend"))
1305 rc = PR_CAP_BE | PR_CAP_RS;
1306 else if (!strcmp(args[0], "ruleset"))
1307 rc = PR_CAP_RS;
1308 else
1309 rc = PR_CAP_NONE;
1310
1311 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 if (!*args[1]) {
1313 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1314 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1315 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001316 err_code |= ERR_ALERT | ERR_ABORT;
1317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001319
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001320 err = invalid_char(args[1]);
1321 if (err) {
1322 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1323 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001325 }
1326
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001327 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1328 /*
1329 * If there are two proxies with the same name only following
1330 * combinations are allowed:
1331 *
1332 * listen backend frontend ruleset
1333 * listen - - - -
1334 * backend - - OK -
1335 * frontend - OK - -
1336 * ruleset - - - -
1337 */
1338
1339 if (!strcmp(curproxy->id, args[1]) &&
1340 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1341 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001342 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1343 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1344 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001345 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001346 }
1347 }
1348
Willy Tarreaubaaee002006-06-26 02:48:02 +02001349 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1350 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_ABORT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001354
Willy Tarreau97cb7802010-01-03 20:23:58 +01001355 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 curproxy->next = proxy;
1357 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001358 curproxy->conf.file = file;
1359 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001360 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001362 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363
1364 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001365 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001366 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001367 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_FATAL;
1369 goto out;
1370 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001371 new = curproxy->listen;
1372 while (new != last) {
1373 new->conf.file = file;
1374 new->conf.line = linenum;
1375 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001376 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 }
1379
1380 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001381 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001382 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001383
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001386 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001387 curproxy->no_options = defproxy.no_options;
1388 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001389 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001390 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001391 curproxy->except_net = defproxy.except_net;
1392 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001393 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001394 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001395
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001396 if (defproxy.fwdfor_hdr_len) {
1397 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1398 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1399 }
1400
Willy Tarreaub86db342009-11-30 11:50:16 +01001401 if (defproxy.orgto_hdr_len) {
1402 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1403 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1404 }
1405
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406 if (curproxy->cap & PR_CAP_FE) {
1407 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001408 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001409 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410
1411 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001412 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1413 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001414
1415 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
Willy Tarreau977b8e42006-12-29 14:19:17 +01001418 if (curproxy->cap & PR_CAP_BE) {
1419 curproxy->fullconn = defproxy.fullconn;
1420 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001422 if (defproxy.check_req) {
1423 curproxy->check_req = calloc(1, defproxy.check_len);
1424 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001426 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001427
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001428 if (defproxy.expect_str) {
1429 curproxy->expect_str = strdup(defproxy.expect_str);
1430 if (defproxy.expect_regex) {
1431 /* note: this regex is known to be valid */
1432 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1433 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1434 }
1435 }
1436
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437 if (defproxy.cookie_name)
1438 curproxy->cookie_name = strdup(defproxy.cookie_name);
1439 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001440 if (defproxy.cookie_domain)
1441 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001442
Willy Tarreau31936852010-10-06 16:59:56 +02001443 if (defproxy.cookie_maxidle)
1444 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1445
1446 if (defproxy.cookie_maxlife)
1447 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1448
Emeric Brun647caf12009-06-30 17:57:00 +02001449 if (defproxy.rdp_cookie_name)
1450 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1451 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1452
Willy Tarreau01732802007-11-01 22:48:15 +01001453 if (defproxy.url_param_name)
1454 curproxy->url_param_name = strdup(defproxy.url_param_name);
1455 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001456
Benoitaffb4812009-03-25 13:02:10 +01001457 if (defproxy.hh_name)
1458 curproxy->hh_name = strdup(defproxy.hh_name);
1459 curproxy->hh_len = defproxy.hh_len;
1460 curproxy->hh_match_domain = defproxy.hh_match_domain;
1461
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001462 if (defproxy.iface_name)
1463 curproxy->iface_name = strdup(defproxy.iface_name);
1464 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001467 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001468 if (defproxy.capture_name)
1469 curproxy->capture_name = strdup(defproxy.capture_name);
1470 curproxy->capture_namelen = defproxy.capture_namelen;
1471 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001475 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001476 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001477 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001478 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 curproxy->uri_auth = defproxy.uri_auth;
1480 curproxy->mon_net = defproxy.mon_net;
1481 curproxy->mon_mask = defproxy.mon_mask;
1482 if (defproxy.monitor_uri)
1483 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1484 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001485 if (defproxy.defbe.name)
1486 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001487 }
1488
1489 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001490 curproxy->timeout.connect = defproxy.timeout.connect;
1491 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001492 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001493 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001494 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001495 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001496 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 curproxy->source_addr = defproxy.source_addr;
1498 }
1499
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 curproxy->mode = defproxy.mode;
1501 curproxy->logfac1 = defproxy.logfac1;
1502 curproxy->logsrv1 = defproxy.logsrv1;
1503 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001504 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 curproxy->logfac2 = defproxy.logfac2;
1506 curproxy->logsrv2 = defproxy.logsrv2;
1507 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001508 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001510 curproxy->conf.used_listener_id = EB_ROOT;
1511 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001512
Willy Tarreau93893792009-07-23 13:19:11 +02001513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 }
1515 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1516 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001517 /* FIXME-20070101: we should do this too at the end of the
1518 * config parsing to free all default values.
1519 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001520 free(defproxy.check_req);
1521 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001522 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001523 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001524 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001525 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001526 free(defproxy.capture_name);
1527 free(defproxy.monitor_uri);
1528 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001529 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001530 free(defproxy.fwdfor_hdr_name);
1531 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001532 free(defproxy.orgto_hdr_name);
1533 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001534 free(defproxy.expect_str);
1535 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001536
Willy Tarreaua534fea2008-08-03 12:19:50 +02001537 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001538 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 /* we cannot free uri_auth because it might already be used */
1541 init_default_instance();
1542 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001543 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545 }
1546 else if (curproxy == NULL) {
1547 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 }
1551
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552
1553 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001555 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001556 int cur_arg;
1557
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 if (curproxy == &defproxy) {
1559 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001560 err_code |= ERR_ALERT | ERR_FATAL;
1561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001563 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001564 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
Emeric Bruned760922010-10-22 17:59:25 +02001566 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001567 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001572
1573 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001574
1575 /* NOTE: the following line might create several listeners if there
1576 * are comma-separated IPs or port ranges. So all further processing
1577 * will have to be applied to all listeners created after last_listen.
1578 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001579 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001583
Willy Tarreau90a570f2009-10-04 20:54:54 +02001584 new_listen = curproxy->listen;
1585 while (new_listen != last_listen) {
1586 new_listen->conf.file = file;
1587 new_listen->conf.line = linenum;
1588 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001589 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001590 }
1591
Emeric Bruned760922010-10-22 17:59:25 +02001592 /* Set default global rights and owner for unix bind */
1593 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1594 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1595 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001596 cur_arg = 2;
1597 while (*(args[cur_arg])) {
1598 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1599#ifdef SO_BINDTODEVICE
1600 struct listener *l;
1601
Emeric Bruned760922010-10-22 17:59:25 +02001602 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1603 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1604 file, linenum, args[0], args[cur_arg]);
1605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
1607 }
1608
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001609 if (!*args[cur_arg + 1]) {
1610 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001612 err_code |= ERR_ALERT | ERR_FATAL;
1613 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001614 }
1615
1616 for (l = curproxy->listen; l != last_listen; l = l->next)
1617 l->interface = strdup(args[cur_arg + 1]);
1618
1619 global.last_checks |= LSTCHK_NETADM;
1620
1621 cur_arg += 2;
1622 continue;
1623#else
1624 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1625 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001628#endif
1629 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001630 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1631#ifdef TCP_MAXSEG
1632 struct listener *l;
1633 int mss;
1634
Emeric Bruned760922010-10-22 17:59:25 +02001635 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1636 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1637 file, linenum, args[0], args[cur_arg]);
1638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreaube1b9182009-06-14 18:48:19 +02001642 if (!*args[cur_arg + 1]) {
1643 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001647 }
1648
Willy Tarreau48a7e722010-12-24 15:26:39 +01001649 mss = atoi(args[cur_arg + 1]);
1650 if (!mss || abs(mss) > 65535) {
1651 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001655 }
1656
1657 for (l = curproxy->listen; l != last_listen; l = l->next)
1658 l->maxseg = mss;
1659
1660 cur_arg += 2;
1661 continue;
1662#else
1663 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1664 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667#endif
1668 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001669
1670 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1671#ifdef TCP_DEFER_ACCEPT
1672 struct listener *l;
1673
1674 for (l = curproxy->listen; l != last_listen; l = l->next)
1675 l->options |= LI_O_DEF_ACCEPT;
1676
1677 cur_arg ++;
1678 continue;
1679#else
1680 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1681 file, linenum, args[0], args[cur_arg]);
1682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
1684#endif
1685 }
1686
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001687 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001688#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001689 struct listener *l;
1690
Emeric Bruned760922010-10-22 17:59:25 +02001691 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1692 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1693 file, linenum, args[0], args[cur_arg]);
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
1696 }
1697
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001698 for (l = curproxy->listen; l != last_listen; l = l->next)
1699 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001700
1701 cur_arg ++;
1702 continue;
1703#else
1704 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1705 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001708#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001709 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001710
Willy Tarreau8a956912010-10-15 14:27:08 +02001711 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1712 struct listener *l;
1713
1714 for (l = curproxy->listen; l != last_listen; l = l->next)
1715 l->options |= LI_O_ACC_PROXY;
1716
1717 cur_arg ++;
1718 continue;
1719 }
1720
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001721 if (!strcmp(args[cur_arg], "name")) {
1722 struct listener *l;
1723
1724 for (l = curproxy->listen; l != last_listen; l = l->next)
1725 l->name = strdup(args[cur_arg + 1]);
1726
1727 cur_arg += 2;
1728 continue;
1729 }
1730
1731 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001732 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001733 struct listener *l;
1734
1735 if (curproxy->listen->next != last_listen) {
1736 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1737 file, linenum, args[cur_arg]);
1738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
1740 }
1741
1742 if (!*args[cur_arg + 1]) {
1743 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1744 file, linenum, args[cur_arg]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001750 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001751
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001752 if (curproxy->listen->luid <= 0) {
1753 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001754 file, linenum);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001759 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1760 if (node) {
1761 l = container_of(node, struct listener, conf.id);
1762 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1763 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1768
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 cur_arg += 2;
1770 continue;
1771 }
1772
Emeric Bruned760922010-10-22 17:59:25 +02001773 if (!strcmp(args[cur_arg], "mode")) {
1774
1775 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1776 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1777 file, linenum, args[0], args[cur_arg]);
1778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
1780 }
1781
1782 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1783
1784 cur_arg += 2;
1785 continue;
1786 }
1787
1788 if (!strcmp(args[cur_arg], "uid")) {
1789
1790 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1798 cur_arg += 2;
1799 continue;
1800 }
1801
1802 if (!strcmp(args[cur_arg], "gid")) {
1803
1804 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1805 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1806 file, linenum, args[0], args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1812 cur_arg += 2;
1813 continue;
1814 }
1815
1816 if (!strcmp(args[cur_arg], "user")) {
1817 struct passwd *user;
1818
1819 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1820 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1821 file, linenum, args[0], args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825 user = getpwnam(args[cur_arg + 1]);
1826 if (!user) {
1827 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1828 file, linenum, args[0], args[cur_arg + 1 ]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 curproxy->listen->perm.ux.uid = user->pw_uid;
1834 cur_arg += 2;
1835 continue;
1836 }
1837
1838 if (!strcmp(args[cur_arg], "group")) {
1839 struct group *group;
1840
1841 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1843 file, linenum, args[0], args[cur_arg]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847 group = getgrnam(args[cur_arg + 1]);
1848 if (!group) {
1849 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1850 file, linenum, args[0], args[cur_arg + 1 ]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 curproxy->listen->perm.ux.gid = group->gr_gid;
1856 cur_arg += 2;
1857 continue;
1858 }
1859
Willy Tarreau8a956912010-10-15 14:27:08 +02001860 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001861 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001864 }
Willy Tarreau93893792009-07-23 13:19:11 +02001865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001866 }
1867 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1868 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1869 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001873 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876
Willy Tarreaubaaee002006-06-26 02:48:02 +02001877 /* flush useless bits */
1878 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001880 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001881 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001882 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884
Willy Tarreau1c47f852006-07-09 08:22:27 +02001885 if (!*args[1]) {
1886 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001888 err_code |= ERR_ALERT | ERR_FATAL;
1889 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001890 }
1891
Willy Tarreaua534fea2008-08-03 12:19:50 +02001892 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001893 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001894 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001895 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001896 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1897
Willy Tarreau93893792009-07-23 13:19:11 +02001898 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001899 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1901 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1902 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1903 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1904 else {
1905 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908 }
1909 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001910 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001911 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001912
1913 if (curproxy == &defproxy) {
1914 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1915 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001918 }
1919
1920 if (!*args[1]) {
1921 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001923 err_code |= ERR_ALERT | ERR_FATAL;
1924 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001925 }
1926
1927 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001928 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001929
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001930 if (curproxy->uuid <= 0) {
1931 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001932 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935 }
1936
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001937 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1938 if (node) {
1939 struct proxy *target = container_of(node, struct proxy, conf.id);
1940 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1941 file, linenum, proxy_type_str(curproxy), curproxy->id,
1942 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
1945 }
1946 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001947 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001948 else if (!strcmp(args[0], "description")) {
1949 int i, len=0;
1950 char *d;
1951
Cyril Bonté99ed3272010-01-24 23:29:44 +01001952 if (curproxy == &defproxy) {
1953 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1954 file, linenum, args[0]);
1955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
1957 }
1958
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001959 if (!*args[1]) {
1960 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1961 file, linenum, args[0]);
1962 return -1;
1963 }
1964
1965 for(i=1; *args[i]; i++)
1966 len += strlen(args[i])+1;
1967
1968 d = (char *)calloc(1, len);
1969 curproxy->desc = d;
1970
1971 d += sprintf(d, "%s", args[1]);
1972 for(i=2; *args[i]; i++)
1973 d += sprintf(d, " %s", args[i]);
1974
1975 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1977 curproxy->state = PR_STSTOPPED;
1978 }
1979 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1980 curproxy->state = PR_STNEW;
1981 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001982 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1983 int cur_arg = 1;
1984 unsigned int set = 0;
1985
1986 while (*args[cur_arg]) {
1987 int u;
1988 if (strcmp(args[cur_arg], "all") == 0) {
1989 set = 0;
1990 break;
1991 }
1992 else if (strcmp(args[cur_arg], "odd") == 0) {
1993 set |= 0x55555555;
1994 }
1995 else if (strcmp(args[cur_arg], "even") == 0) {
1996 set |= 0xAAAAAAAA;
1997 }
1998 else {
1999 u = str2uic(args[cur_arg]);
2000 if (u < 1 || u > 32) {
2001 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2002 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002005 }
2006 if (u > global.nbproc) {
2007 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2008 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002009 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002010 }
2011 set |= 1 << (u - 1);
2012 }
2013 cur_arg++;
2014 }
2015 curproxy->bind_proc = set;
2016 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002017 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002018 if (curproxy == &defproxy) {
2019 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002022 }
2023
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002024 err = invalid_char(args[1]);
2025 if (err) {
2026 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2027 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002029 }
2030
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002031 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2032 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2033 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002036 }
2037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2039 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002042 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002043
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044 if (*(args[1]) == 0) {
2045 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2046 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002049 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002050
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002051 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002052 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002053 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002054 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002055 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 curproxy->cookie_name = strdup(args[1]);
2057 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 cur_arg = 2;
2060 while (*(args[cur_arg])) {
2061 if (!strcmp(args[cur_arg], "rewrite")) {
2062 curproxy->options |= PR_O_COOK_RW;
2063 }
2064 else if (!strcmp(args[cur_arg], "indirect")) {
2065 curproxy->options |= PR_O_COOK_IND;
2066 }
2067 else if (!strcmp(args[cur_arg], "insert")) {
2068 curproxy->options |= PR_O_COOK_INS;
2069 }
2070 else if (!strcmp(args[cur_arg], "nocache")) {
2071 curproxy->options |= PR_O_COOK_NOC;
2072 }
2073 else if (!strcmp(args[cur_arg], "postonly")) {
2074 curproxy->options |= PR_O_COOK_POST;
2075 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002076 else if (!strcmp(args[cur_arg], "preserve")) {
2077 curproxy->options2 |= PR_O2_COOK_PSV;
2078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 else if (!strcmp(args[cur_arg], "prefix")) {
2080 curproxy->options |= PR_O_COOK_PFX;
2081 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002082 else if (!strcmp(args[cur_arg], "domain")) {
2083 if (!*args[cur_arg + 1]) {
2084 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2085 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002088 }
2089
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002090 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002091 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002092 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2093 " dots nor does not start with a dot."
2094 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002095 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002096 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 }
2098
2099 err = invalid_domainchar(args[cur_arg + 1]);
2100 if (err) {
2101 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2102 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002105 }
2106
Willy Tarreau68a897b2009-12-03 23:28:34 +01002107 if (!curproxy->cookie_domain) {
2108 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2109 } else {
2110 /* one domain was already specified, add another one by
2111 * building the string which will be returned along with
2112 * the cookie.
2113 */
2114 char *new_ptr;
2115 int new_len = strlen(curproxy->cookie_domain) +
2116 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2117 new_ptr = malloc(new_len);
2118 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2119 free(curproxy->cookie_domain);
2120 curproxy->cookie_domain = new_ptr;
2121 }
Willy Tarreau31936852010-10-06 16:59:56 +02002122 cur_arg++;
2123 }
2124 else if (!strcmp(args[cur_arg], "maxidle")) {
2125 unsigned int maxidle;
2126 const char *res;
2127
2128 if (!*args[cur_arg + 1]) {
2129 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2130 file, linenum, args[cur_arg]);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
2133 }
2134
2135 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2136 if (res) {
2137 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2138 file, linenum, *res, args[cur_arg]);
2139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
2141 }
2142 curproxy->cookie_maxidle = maxidle;
2143 cur_arg++;
2144 }
2145 else if (!strcmp(args[cur_arg], "maxlife")) {
2146 unsigned int maxlife;
2147 const char *res;
2148
2149 if (!*args[cur_arg + 1]) {
2150 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2151 file, linenum, args[cur_arg]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155
2156 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2157 if (res) {
2158 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2159 file, linenum, *res, args[cur_arg]);
2160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
2162 }
2163 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002164 cur_arg++;
2165 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002166 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002167 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 +02002168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 }
2172 cur_arg++;
2173 }
2174 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2175 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2176 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 }
2179
2180 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2181 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2182 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002183 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002185
2186 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2187 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2188 file, linenum);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002191 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002192 else if (!strcmp(args[0], "persist")) { /* persist */
2193 if (*(args[1]) == 0) {
2194 Alert("parsing [%s:%d] : missing persist method.\n",
2195 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002198 }
2199
2200 if (!strncmp(args[1], "rdp-cookie", 10)) {
2201 curproxy->options2 |= PR_O2_RDPC_PRST;
2202
Emeric Brunb982a3d2010-01-04 15:45:53 +01002203 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002204 const char *beg, *end;
2205
2206 beg = args[1] + 11;
2207 end = strchr(beg, ')');
2208
2209 if (!end || end == beg) {
2210 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002214 }
2215
2216 free(curproxy->rdp_cookie_name);
2217 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2218 curproxy->rdp_cookie_len = end-beg;
2219 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002220 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002221 free(curproxy->rdp_cookie_name);
2222 curproxy->rdp_cookie_name = strdup("msts");
2223 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2224 }
2225 else { /* syntax */
2226 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002230 }
2231 }
2232 else {
2233 Alert("parsing [%s:%d] : unknown persist method.\n",
2234 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002237 }
2238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002239 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002240 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002242 if (curproxy == &defproxy) {
2243 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2244 err_code |= ERR_ALERT | ERR_FATAL;
2245 goto out;
2246 }
2247
Willy Tarreau977b8e42006-12-29 14:19:17 +01002248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002250
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002252 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 }
2257 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002258 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002259 curproxy->appsession_name = strdup(args[1]);
2260 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2261 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002262 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2263 if (err) {
2264 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2265 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002268 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002269 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002270
Willy Tarreau51041c72007-09-09 21:56:53 +02002271 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2272 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_ABORT;
2274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002276
2277 cur_arg = 6;
2278 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002279 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2280 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002281 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002282 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002283 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002284 } else if (!strcmp(args[cur_arg], "prefix")) {
2285 curproxy->options2 |= PR_O2_AS_PFX;
2286 } else if (!strcmp(args[cur_arg], "mode")) {
2287 if (!*args[cur_arg + 1]) {
2288 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2289 file, linenum, args[0], args[cur_arg]);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294 cur_arg++;
2295 if (!strcmp(args[cur_arg], "query-string")) {
2296 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2297 curproxy->options2 |= PR_O2_AS_M_QS;
2298 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2299 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2300 curproxy->options2 |= PR_O2_AS_M_PP;
2301 } else {
2302 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002307 cur_arg++;
2308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 } /* Url App Session */
2310 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002311 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002313
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002315 if (curproxy == &defproxy) {
2316 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 if (*(args[4]) == 0) {
2322 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2323 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002327 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 curproxy->capture_name = strdup(args[2]);
2329 curproxy->capture_namelen = strlen(curproxy->capture_name);
2330 curproxy->capture_len = atol(args[4]);
2331 if (curproxy->capture_len >= CAPTURE_LEN) {
2332 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2333 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002334 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 curproxy->capture_len = CAPTURE_LEN - 1;
2336 }
2337 curproxy->to_log |= LW_COOKIE;
2338 }
2339 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2340 struct cap_hdr *hdr;
2341
2342 if (curproxy == &defproxy) {
2343 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 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
2347
2348 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2349 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2350 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354
2355 hdr = calloc(sizeof(struct cap_hdr), 1);
2356 hdr->next = curproxy->req_cap;
2357 hdr->name = strdup(args[3]);
2358 hdr->namelen = strlen(args[3]);
2359 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002360 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 hdr->index = curproxy->nb_req_cap++;
2362 curproxy->req_cap = hdr;
2363 curproxy->to_log |= LW_REQHDR;
2364 }
2365 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2366 struct cap_hdr *hdr;
2367
2368 if (curproxy == &defproxy) {
2369 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373
2374 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2375 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2376 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_ALERT | ERR_FATAL;
2378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 }
2380 hdr = calloc(sizeof(struct cap_hdr), 1);
2381 hdr->next = curproxy->rsp_cap;
2382 hdr->name = strdup(args[3]);
2383 hdr->namelen = strlen(args[3]);
2384 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002385 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 hdr->index = curproxy->nb_rsp_cap++;
2387 curproxy->rsp_cap = hdr;
2388 curproxy->to_log |= LW_RSPHDR;
2389 }
2390 else {
2391 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002400
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 if (*(args[1]) == 0) {
2402 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2403 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
2407 curproxy->conn_retries = atol(args[1]);
2408 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002409 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002410 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002411
2412 if (curproxy == &defproxy) {
2413 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
2416 }
2417
Willy Tarreauff011f22011-01-06 17:51:27 +01002418 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 +01002419 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2420 file, linenum, args[0]);
2421 err_code |= ERR_WARN;
2422 }
2423
Willy Tarreauff011f22011-01-06 17:51:27 +01002424 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425
Willy Tarreauff011f22011-01-06 17:51:27 +01002426 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002427 err_code |= ERR_ALERT | ERR_ABORT;
2428 goto out;
2429 }
2430
Willy Tarreauff011f22011-01-06 17:51:27 +01002431 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2432 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002433 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002434 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002439 }
2440
Willy Tarreauef6494c2010-01-28 17:12:36 +01002441 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002442 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2443 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002446 }
2447
Willy Tarreauef6494c2010-01-28 17:12:36 +01002448 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002449 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2450 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002453 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002454
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002455 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002456 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002457 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002458 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002459 struct redirect_rule *rule;
2460 int cur_arg;
2461 int type = REDIRECT_TYPE_NONE;
2462 int code = 302;
2463 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002464 char *cookie = NULL;
2465 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002466 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002467
Cyril Bonté99ed3272010-01-24 23:29:44 +01002468 if (curproxy == &defproxy) {
2469 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002474 cur_arg = 1;
2475 while (*(args[cur_arg])) {
2476 if (!strcmp(args[cur_arg], "location")) {
2477 if (!*args[cur_arg + 1]) {
2478 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2479 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002482 }
2483
2484 type = REDIRECT_TYPE_LOCATION;
2485 cur_arg++;
2486 destination = args[cur_arg];
2487 }
2488 else if (!strcmp(args[cur_arg], "prefix")) {
2489 if (!*args[cur_arg + 1]) {
2490 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2491 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002494 }
2495
2496 type = REDIRECT_TYPE_PREFIX;
2497 cur_arg++;
2498 destination = args[cur_arg];
2499 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002500 else if (!strcmp(args[cur_arg], "set-cookie")) {
2501 if (!*args[cur_arg + 1]) {
2502 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2503 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002506 }
2507
2508 cur_arg++;
2509 cookie = args[cur_arg];
2510 cookie_set = 1;
2511 }
2512 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2513 if (!*args[cur_arg + 1]) {
2514 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2515 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002518 }
2519
2520 cur_arg++;
2521 cookie = args[cur_arg];
2522 cookie_set = 0;
2523 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002524 else if (!strcmp(args[cur_arg],"code")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2527 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531 cur_arg++;
2532 code = atol(args[cur_arg]);
2533 if (code < 301 || code > 303) {
2534 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2535 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002538 }
2539 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002540 else if (!strcmp(args[cur_arg],"drop-query")) {
2541 flags |= REDIRECT_FLAG_DROP_QS;
2542 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002543 else if (!strcmp(args[cur_arg],"append-slash")) {
2544 flags |= REDIRECT_FLAG_APPEND_SLASH;
2545 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002546 else if (strcmp(args[cur_arg], "if") == 0 ||
2547 strcmp(args[cur_arg], "unless") == 0) {
2548 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2549 if (!cond) {
2550 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2551 file, linenum, args[0]);
2552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
2554 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002555 break;
2556 }
2557 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002558 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 +02002559 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 }
2563 cur_arg++;
2564 }
2565
2566 if (type == REDIRECT_TYPE_NONE) {
2567 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2568 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002571 }
2572
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002573 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2574 rule->cond = cond;
2575 rule->rdr_str = strdup(destination);
2576 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002577 if (cookie) {
2578 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002579 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002580 */
2581 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002582 if (cookie_set) {
2583 rule->cookie_str = malloc(rule->cookie_len + 10);
2584 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2585 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2586 rule->cookie_len += 9;
2587 } else {
2588 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002589 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002590 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2591 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002592 }
2593 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002594 rule->type = type;
2595 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002596 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002597 LIST_INIT(&rule->list);
2598 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002599 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2600 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002602 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002603 struct switching_rule *rule;
2604
Willy Tarreaub099aca2008-10-12 17:26:37 +02002605 if (curproxy == &defproxy) {
2606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002609 }
2610
Willy Tarreau55ea7572007-06-17 19:56:27 +02002611 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002613
2614 if (*(args[1]) == 0) {
2615 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002616 err_code |= ERR_ALERT | ERR_FATAL;
2617 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618 }
2619
Willy Tarreauef6494c2010-01-28 17:12:36 +01002620 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002621 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2622 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002625 }
2626
Willy Tarreauef6494c2010-01-28 17:12:36 +01002627 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002628 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002629 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002632 }
2633
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002634 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002635
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2637 rule->cond = cond;
2638 rule->be.name = strdup(args[1]);
2639 LIST_INIT(&rule->list);
2640 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2641 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002642 else if ((!strcmp(args[0], "force-persist")) ||
2643 (!strcmp(args[0], "ignore-persist"))) {
2644 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002645
2646 if (curproxy == &defproxy) {
2647 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2653 err_code |= ERR_WARN;
2654
Willy Tarreauef6494c2010-01-28 17:12:36 +01002655 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002656 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2657 file, linenum, args[0]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661
Willy Tarreauef6494c2010-01-28 17:12:36 +01002662 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002663 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2664 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002665 err_code |= ERR_ALERT | ERR_FATAL;
2666 goto out;
2667 }
2668
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002669 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002670
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002671 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002672 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002673 if (!strcmp(args[0], "force-persist")) {
2674 rule->type = PERSIST_TYPE_FORCE;
2675 } else {
2676 rule->type = PERSIST_TYPE_IGNORE;
2677 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002678 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002679 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002680 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002681 else if (!strcmp(args[0], "stick-table")) {
2682 int myidx = 1;
2683
Emeric Brun32da3c42010-09-23 18:39:19 +02002684 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002685 curproxy->table.type = (unsigned int)-1;
2686 while (*args[myidx]) {
2687 const char *err;
2688
2689 if (strcmp(args[myidx], "size") == 0) {
2690 myidx++;
2691 if (!*(args[myidx])) {
2692 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2693 file, linenum, args[myidx-1]);
2694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2698 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2699 file, linenum, *err, args[myidx-1]);
2700 err_code |= ERR_ALERT | ERR_FATAL;
2701 goto out;
2702 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002703 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002704 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002705 else if (strcmp(args[myidx], "peers") == 0) {
2706 myidx++;
2707 if (!*(args[myidx])) {
2708 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2709 file, linenum, args[myidx-1]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713 curproxy->table.peers.name = strdup(args[myidx++]);
2714 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002715 else if (strcmp(args[myidx], "expire") == 0) {
2716 myidx++;
2717 if (!*(args[myidx])) {
2718 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2719 file, linenum, args[myidx-1]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2724 if (err) {
2725 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2726 file, linenum, *err, args[myidx-1]);
2727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
2730 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002731 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002732 }
2733 else if (strcmp(args[myidx], "nopurge") == 0) {
2734 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002735 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002736 }
2737 else if (strcmp(args[myidx], "type") == 0) {
2738 myidx++;
2739 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2740 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2741 file, linenum, args[myidx]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002745 /* myidx already points to next arg */
2746 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002747 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002748 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002749 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002750
2751 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002752 nw = args[myidx];
2753 while (*nw) {
2754 /* the "store" keyword supports a comma-separated list */
2755 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002756 sa = NULL; /* store arg */
2757 while (*nw && *nw != ',') {
2758 if (*nw == '(') {
2759 *nw = 0;
2760 sa = ++nw;
2761 while (*nw != ')') {
2762 if (!*nw) {
2763 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2764 file, linenum, args[0], cw);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
2768 nw++;
2769 }
2770 *nw = '\0';
2771 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002772 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002773 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002774 if (*nw)
2775 *nw++ = '\0';
2776 type = stktable_get_data_type(cw);
2777 if (type < 0) {
2778 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2779 file, linenum, args[0], cw);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
Willy Tarreauac782882010-06-20 10:41:54 +02002783
2784 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2785 switch (err) {
2786 case PE_NONE: break;
2787 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002788 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2789 file, linenum, args[0], cw);
2790 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002791 break;
2792
2793 case PE_ARG_MISSING:
2794 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2795 file, linenum, args[0], cw);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798
2799 case PE_ARG_NOT_USED:
2800 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2801 file, linenum, args[0], cw);
2802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
2804
2805 default:
2806 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2807 file, linenum, args[0], cw);
2808 err_code |= ERR_ALERT | ERR_FATAL;
2809 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002810 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002811 }
2812 myidx++;
2813 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002814 else {
2815 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2816 file, linenum, args[myidx]);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002819 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 }
2821
2822 if (!curproxy->table.size) {
2823 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2824 file, linenum);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827 }
2828
2829 if (curproxy->table.type == (unsigned int)-1) {
2830 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2831 file, linenum);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
2834 }
2835 }
2836 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002837 struct sticking_rule *rule;
2838 struct pattern_expr *expr;
2839 int myidx = 0;
2840 const char *name = NULL;
2841 int flags;
2842
2843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
2849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2850 err_code |= ERR_WARN;
2851 goto out;
2852 }
2853
2854 myidx++;
2855 if ((strcmp(args[myidx], "store") == 0) ||
2856 (strcmp(args[myidx], "store-request") == 0)) {
2857 myidx++;
2858 flags = STK_IS_STORE;
2859 }
2860 else if (strcmp(args[myidx], "store-response") == 0) {
2861 myidx++;
2862 flags = STK_IS_STORE | STK_ON_RSP;
2863 }
2864 else if (strcmp(args[myidx], "match") == 0) {
2865 myidx++;
2866 flags = STK_IS_MATCH;
2867 }
2868 else if (strcmp(args[myidx], "on") == 0) {
2869 myidx++;
2870 flags = STK_IS_MATCH | STK_IS_STORE;
2871 }
2872 else {
2873 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 if (*(args[myidx]) == 0) {
2879 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
Emeric Brun485479d2010-09-23 18:02:19 +02002884 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002885 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002886 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
2891 if (flags & STK_ON_RSP) {
2892 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2893 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2894 file, linenum, args[0], expr->fetch->kw);
2895 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002896 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002897 goto out;
2898 }
2899 } else {
2900 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2901 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2902 file, linenum, args[0], expr->fetch->kw);
2903 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002904 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002905 goto out;
2906 }
2907 }
2908
2909 if (strcmp(args[myidx], "table") == 0) {
2910 myidx++;
2911 name = args[myidx++];
2912 }
2913
Willy Tarreauef6494c2010-01-28 17:12:36 +01002914 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002916 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2917 file, linenum, args[0]);
2918 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002919 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002920 goto out;
2921 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002922 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002923 else if (*(args[myidx])) {
2924 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2925 file, linenum, args[0], args[myidx]);
2926 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002927 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002928 goto out;
2929 }
Emeric Brun97679e72010-09-23 17:56:44 +02002930 if (flags & STK_ON_RSP)
2931 err_code |= warnif_cond_requires_req(cond, file, linenum);
2932 else
2933 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002934
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2936 rule->cond = cond;
2937 rule->expr = expr;
2938 rule->flags = flags;
2939 rule->table.name = name ? strdup(name) : NULL;
2940 LIST_INIT(&rule->list);
2941 if (flags & STK_ON_RSP)
2942 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2943 else
2944 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002947 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002948 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002949
Willy Tarreaubaaee002006-06-26 02:48:02 +02002950 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2951 curproxy->uri_auth = NULL; /* we must detach from the default config */
2952
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002953 if (!*args[1]) {
2954 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002955 } else if (!strcmp(args[1], "admin")) {
2956 struct stats_admin_rule *rule;
2957
2958 if (curproxy == &defproxy) {
2959 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
2964 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2965 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2966 err_code |= ERR_ALERT | ERR_ABORT;
2967 goto out;
2968 }
2969
2970 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2971 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2972 file, linenum, args[0], args[1]);
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
2976 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2977 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2978 file, linenum, args[0], args[1]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
2983 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2984
2985 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2986 rule->cond = cond;
2987 LIST_INIT(&rule->list);
2988 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 } else if (!strcmp(args[1], "uri")) {
2990 if (*(args[2]) == 0) {
2991 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2995 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_ABORT;
2997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 } else if (!strcmp(args[1], "realm")) {
3000 if (*(args[2]) == 0) {
3001 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3005 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_ABORT;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003009 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003010 unsigned interval;
3011
3012 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3013 if (err) {
3014 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3015 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003018 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3019 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003020 err_code |= ERR_ALERT | ERR_ABORT;
3021 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003022 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003023 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003024 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003025
3026 if (curproxy == &defproxy) {
3027 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
3030 }
3031
3032 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3033 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3034 err_code |= ERR_ALERT | ERR_ABORT;
3035 goto out;
3036 }
3037
Willy Tarreauff011f22011-01-06 17:51:27 +01003038 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3039 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003040 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3041 file, linenum, args[0]);
3042 err_code |= ERR_WARN;
3043 }
3044
Willy Tarreauff011f22011-01-06 17:51:27 +01003045 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046
Willy Tarreauff011f22011-01-06 17:51:27 +01003047 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003048 err_code |= ERR_ALERT | ERR_ABORT;
3049 goto out;
3050 }
3051
Willy Tarreauff011f22011-01-06 17:51:27 +01003052 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3053 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 } else if (!strcmp(args[1], "auth")) {
3056 if (*(args[2]) == 0) {
3057 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3061 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003062 err_code |= ERR_ALERT | ERR_ABORT;
3063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064 }
3065 } else if (!strcmp(args[1], "scope")) {
3066 if (*(args[2]) == 0) {
3067 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_ABORT;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075 } else if (!strcmp(args[1], "enable")) {
3076 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3077 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_ABORT;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003081 } else if (!strcmp(args[1], "hide-version")) {
3082 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3083 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003084 err_code |= ERR_ALERT | ERR_ABORT;
3085 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003086 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003087 } else if (!strcmp(args[1], "show-legends")) {
3088 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3089 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3090 err_code |= ERR_ALERT | ERR_ABORT;
3091 goto out;
3092 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003093 } else if (!strcmp(args[1], "show-node")) {
3094
3095 if (*args[2]) {
3096 int i;
3097 char c;
3098
3099 for (i=0; args[2][i]; i++) {
3100 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003101 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3102 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003103 break;
3104 }
3105
3106 if (!i || args[2][i]) {
3107 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3108 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3109 file, linenum, args[0], args[1]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113 }
3114
3115 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3116 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3117 err_code |= ERR_ALERT | ERR_ABORT;
3118 goto out;
3119 }
3120 } else if (!strcmp(args[1], "show-desc")) {
3121 char *desc = NULL;
3122
3123 if (*args[2]) {
3124 int i, len=0;
3125 char *d;
3126
3127 for(i=2; *args[i]; i++)
3128 len += strlen(args[i])+1;
3129
3130 desc = d = (char *)calloc(1, len);
3131
3132 d += sprintf(d, "%s", args[2]);
3133 for(i=3; *args[i]; i++)
3134 d += sprintf(d, " %s", args[i]);
3135 }
3136
3137 if (!*args[2] && !global.desc)
3138 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3139 file, linenum, args[1]);
3140 else {
3141 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3142 free(desc);
3143 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3144 err_code |= ERR_ALERT | ERR_ABORT;
3145 goto out;
3146 }
3147 free(desc);
3148 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003150stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003151 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 +01003152 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
3156 }
3157 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003158 int optnum;
3159
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003160 if (*(args[1]) == '\0') {
3161 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3162 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003166
3167 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3168 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003169 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3170 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3171 file, linenum, cfg_opts[optnum].name);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
Willy Tarreau93893792009-07-23 13:19:11 +02003175 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3176 err_code |= ERR_WARN;
3177 goto out;
3178 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003179
Willy Tarreau3842f002009-06-14 11:39:52 +02003180 curproxy->no_options &= ~cfg_opts[optnum].val;
3181 curproxy->options &= ~cfg_opts[optnum].val;
3182
3183 switch (kwm) {
3184 case KWM_STD:
3185 curproxy->options |= cfg_opts[optnum].val;
3186 break;
3187 case KWM_NO:
3188 curproxy->no_options |= cfg_opts[optnum].val;
3189 break;
3190 case KWM_DEF: /* already cleared */
3191 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003192 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003193
Willy Tarreau93893792009-07-23 13:19:11 +02003194 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003195 }
3196 }
3197
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003198 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3199 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003200 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3201 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3202 file, linenum, cfg_opts2[optnum].name);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
Willy Tarreau93893792009-07-23 13:19:11 +02003206 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3207 err_code |= ERR_WARN;
3208 goto out;
3209 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003210
Willy Tarreau3842f002009-06-14 11:39:52 +02003211 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3212 curproxy->options2 &= ~cfg_opts2[optnum].val;
3213
3214 switch (kwm) {
3215 case KWM_STD:
3216 curproxy->options2 |= cfg_opts2[optnum].val;
3217 break;
3218 case KWM_NO:
3219 curproxy->no_options2 |= cfg_opts2[optnum].val;
3220 break;
3221 case KWM_DEF: /* already cleared */
3222 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003223 }
Willy Tarreau93893792009-07-23 13:19:11 +02003224 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003225 }
3226 }
3227
Willy Tarreau3842f002009-06-14 11:39:52 +02003228 if (kwm != KWM_STD) {
3229 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003230 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_FATAL;
3232 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003233 }
3234
Emeric Brun3a058f32009-06-30 18:26:00 +02003235 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003237 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003239 if (*(args[2]) != '\0') {
3240 if (!strcmp(args[2], "clf")) {
3241 curproxy->options2 |= PR_O2_CLFLOG;
3242 } else {
3243 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003244 err_code |= ERR_ALERT | ERR_FATAL;
3245 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003246 }
3247 }
3248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 else if (!strcmp(args[1], "tcplog"))
3250 /* generate a detailed TCP log */
3251 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 else if (!strcmp(args[1], "tcpka")) {
3253 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003254 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003255 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003256
3257 if (curproxy->cap & PR_CAP_FE)
3258 curproxy->options |= PR_O_TCP_CLI_KA;
3259 if (curproxy->cap & PR_CAP_BE)
3260 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 }
3262 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_WARN;
3265
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003267 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003268 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003269 curproxy->options2 &= ~PR_O2_CHK_ANY;
3270 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 if (!*args[2]) { /* no argument */
3272 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3273 curproxy->check_len = strlen(DEF_CHECK_REQ);
3274 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003275 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 curproxy->check_req = (char *)malloc(reqlen);
3277 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003278 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003279 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003280 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 if (*args[4])
3282 reqlen += strlen(args[4]);
3283 else
3284 reqlen += strlen("HTTP/1.0");
3285
3286 curproxy->check_req = (char *)malloc(reqlen);
3287 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003288 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003290 }
3291 else if (!strcmp(args[1], "ssl-hello-chk")) {
3292 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003295
Willy Tarreaua534fea2008-08-03 12:19:50 +02003296 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003297 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003298 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003299 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 }
Willy Tarreau23677902007-05-08 23:50:35 +02003301 else if (!strcmp(args[1], "smtpchk")) {
3302 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003303 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003304 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003305 curproxy->options2 &= ~PR_O2_CHK_ANY;
3306 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003307
3308 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3309 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3310 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3311 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3312 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3313 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3314 curproxy->check_req = (char *)malloc(reqlen);
3315 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3316 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3317 } else {
3318 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3319 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3320 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3321 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3322 }
3323 }
3324 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003325 else if (!strcmp(args[1], "pgsql-check")) {
3326 /* use PostgreSQL request to check servers' health */
3327 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3328 err_code |= ERR_WARN;
3329
3330 free(curproxy->check_req);
3331 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003332 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003333 curproxy->options2 |= PR_O2_PGSQL_CHK;
3334
3335 if (*(args[2])) {
3336 int cur_arg = 2;
3337
3338 while (*(args[cur_arg])) {
3339 if (strcmp(args[cur_arg], "user") == 0) {
3340 char * packet;
3341 uint32_t packet_len;
3342 uint32_t pv;
3343
3344 /* suboption header - needs additional argument for it */
3345 if (*(args[cur_arg+1]) == 0) {
3346 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3347 file, linenum, args[0], args[1], args[cur_arg]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351
3352 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3353 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3354 pv = htonl(0x30000); /* protocol version 3.0 */
3355
3356 packet = (char*) calloc(1, packet_len);
3357
3358 memcpy(packet + 4, &pv, 4);
3359
3360 /* copy "user" */
3361 memcpy(packet + 8, "user", 4);
3362
3363 /* copy username */
3364 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3365
3366 free(curproxy->check_req);
3367 curproxy->check_req = packet;
3368 curproxy->check_len = packet_len;
3369
3370 packet_len = htonl(packet_len);
3371 memcpy(packet, &packet_len, 4);
3372 cur_arg += 2;
3373 } else {
3374 /* unknown suboption - catchall */
3375 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3376 file, linenum, args[0], args[1]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380 } /* end while loop */
3381 }
3382 }
3383
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003384 else if (!strcmp(args[1], "redis-check")) {
3385 /* use REDIS PING request to check servers' health */
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3387 err_code |= ERR_WARN;
3388
3389 free(curproxy->check_req);
3390 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003391 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003392 curproxy->options2 |= PR_O2_REDIS_CHK;
3393
3394 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3395 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3396 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3397 }
3398
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003399 else if (!strcmp(args[1], "mysql-check")) {
3400 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003401 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3402 err_code |= ERR_WARN;
3403
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003404 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003405 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003406 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003407 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003408
3409 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3410 * const char mysql40_client_auth_pkt[] = {
3411 * "\x0e\x00\x00" // packet length
3412 * "\x01" // packet number
3413 * "\x00\x00" // client capabilities
3414 * "\x00\x00\x01" // max packet
3415 * "haproxy\x00" // username (null terminated string)
3416 * "\x00" // filler (always 0x00)
3417 * "\x01\x00\x00" // packet length
3418 * "\x00" // packet number
3419 * "\x01" // COM_QUIT command
3420 * };
3421 */
3422
3423 if (*(args[2])) {
3424 int cur_arg = 2;
3425
3426 while (*(args[cur_arg])) {
3427 if (strcmp(args[cur_arg], "user") == 0) {
3428 char *mysqluser;
3429 int packetlen, reqlen, userlen;
3430
3431 /* suboption header - needs additional argument for it */
3432 if (*(args[cur_arg+1]) == 0) {
3433 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3434 file, linenum, args[0], args[1], args[cur_arg]);
3435 err_code |= ERR_ALERT | ERR_FATAL;
3436 goto out;
3437 }
3438 mysqluser = args[cur_arg + 1];
3439 userlen = strlen(mysqluser);
3440 packetlen = userlen + 7;
3441 reqlen = packetlen + 9;
3442
3443 free(curproxy->check_req);
3444 curproxy->check_req = (char *)calloc(1, reqlen);
3445 curproxy->check_len = reqlen;
3446
3447 snprintf(curproxy->check_req, 4, "%c%c%c",
3448 ((unsigned char) packetlen & 0xff),
3449 ((unsigned char) (packetlen >> 8) & 0xff),
3450 ((unsigned char) (packetlen >> 16) & 0xff));
3451
3452 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003453 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003454 curproxy->check_req[8] = 1;
3455 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3456 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3457 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3458 cur_arg += 2;
3459 } else {
3460 /* unknown suboption - catchall */
3461 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3462 file, linenum, args[0], args[1]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 } /* end while loop */
3467 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003468 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003469 else if (!strcmp(args[1], "ldap-check")) {
3470 /* use LDAP request to check servers' health */
3471 free(curproxy->check_req);
3472 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003473 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003474 curproxy->options2 |= PR_O2_LDAP_CHK;
3475
3476 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3477 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3478 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3479 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003480 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003481 int cur_arg;
3482
3483 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3484 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003485 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003486
3487 curproxy->options |= PR_O_FWDFOR;
3488
3489 free(curproxy->fwdfor_hdr_name);
3490 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3491 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3492
3493 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3494 cur_arg = 2;
3495 while (*(args[cur_arg])) {
3496 if (!strcmp(args[cur_arg], "except")) {
3497 /* suboption except - needs additional argument for it */
3498 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3499 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3500 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003503 }
3504 /* flush useless bits */
3505 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003506 cur_arg += 2;
3507 } else if (!strcmp(args[cur_arg], "header")) {
3508 /* suboption header - needs additional argument for it */
3509 if (*(args[cur_arg+1]) == 0) {
3510 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3511 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003514 }
3515 free(curproxy->fwdfor_hdr_name);
3516 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3517 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3518 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003519 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003520 /* unknown suboption - catchall */
3521 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3522 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003525 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003526 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003527 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003528 else if (!strcmp(args[1], "originalto")) {
3529 int cur_arg;
3530
3531 /* insert x-original-to field, but not for the IP address listed as an except.
3532 * set default options (ie: bitfield, header name, etc)
3533 */
3534
3535 curproxy->options |= PR_O_ORGTO;
3536
3537 free(curproxy->orgto_hdr_name);
3538 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3539 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3540
3541 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3542 cur_arg = 2;
3543 while (*(args[cur_arg])) {
3544 if (!strcmp(args[cur_arg], "except")) {
3545 /* suboption except - needs additional argument for it */
3546 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3547 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3548 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003551 }
3552 /* flush useless bits */
3553 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3554 cur_arg += 2;
3555 } else if (!strcmp(args[cur_arg], "header")) {
3556 /* suboption header - needs additional argument for it */
3557 if (*(args[cur_arg+1]) == 0) {
3558 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3559 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003562 }
3563 free(curproxy->orgto_hdr_name);
3564 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3565 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3566 cur_arg += 2;
3567 } else {
3568 /* unknown suboption - catchall */
3569 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3570 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_FATAL;
3572 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003573 }
3574 } /* end while loop */
3575 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 else {
3577 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
Willy Tarreau93893792009-07-23 13:19:11 +02003581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003583 else if (!strcmp(args[0], "default_backend")) {
3584 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003585 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003586
3587 if (*(args[1]) == 0) {
3588 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003591 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003592 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003593 curproxy->defbe.name = strdup(args[1]);
3594 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003595 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003598
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003599 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3600 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 /* enable reconnections to dispatch */
3603 curproxy->options |= PR_O_REDISP;
3604 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003605 else if (!strcmp(args[0], "http-check")) {
3606 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003608
3609 if (strcmp(args[1], "disable-on-404") == 0) {
3610 /* enable a graceful server shutdown on an HTTP 404 response */
3611 curproxy->options |= PR_O_DISABLE404;
3612 }
Willy Tarreauef781042010-01-27 11:53:01 +01003613 else if (strcmp(args[1], "send-state") == 0) {
3614 /* enable emission of the apparent state of a server in HTTP checks */
3615 curproxy->options2 |= PR_O2_CHK_SNDST;
3616 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003617 else if (strcmp(args[1], "expect") == 0) {
3618 const char *ptr_arg;
3619 int cur_arg;
3620
3621 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3622 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
3625 }
3626
3627 cur_arg = 2;
3628 /* consider exclamation marks, sole or at the beginning of a word */
3629 while (*(ptr_arg = args[cur_arg])) {
3630 while (*ptr_arg == '!') {
3631 curproxy->options2 ^= PR_O2_EXP_INV;
3632 ptr_arg++;
3633 }
3634 if (*ptr_arg)
3635 break;
3636 cur_arg++;
3637 }
3638 /* now ptr_arg points to the beginning of a word past any possible
3639 * exclamation mark, and cur_arg is the argument which holds this word.
3640 */
3641 if (strcmp(ptr_arg, "status") == 0) {
3642 if (!*(args[cur_arg + 1])) {
3643 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3644 file, linenum, args[0], args[1], ptr_arg);
3645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
3647 }
3648 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003649 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003650 curproxy->expect_str = strdup(args[cur_arg + 1]);
3651 }
3652 else if (strcmp(ptr_arg, "string") == 0) {
3653 if (!*(args[cur_arg + 1])) {
3654 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3655 file, linenum, args[0], args[1], ptr_arg);
3656 err_code |= ERR_ALERT | ERR_FATAL;
3657 goto out;
3658 }
3659 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003660 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003661 curproxy->expect_str = strdup(args[cur_arg + 1]);
3662 }
3663 else if (strcmp(ptr_arg, "rstatus") == 0) {
3664 if (!*(args[cur_arg + 1])) {
3665 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3666 file, linenum, args[0], args[1], ptr_arg);
3667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
3669 }
3670 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003671 free(curproxy->expect_str);
3672 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3673 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003674 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3675 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3676 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3677 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681 }
3682 else if (strcmp(ptr_arg, "rstring") == 0) {
3683 if (!*(args[cur_arg + 1])) {
3684 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3685 file, linenum, args[0], args[1], ptr_arg);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003690 free(curproxy->expect_str);
3691 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3692 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003693 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3694 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3695 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3696 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700 }
3701 else {
3702 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3703 file, linenum, args[0], args[1], ptr_arg);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003708 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003709 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 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003712 }
3713 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003714 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003715 if (curproxy == &defproxy) {
3716 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003719 }
3720
Willy Tarreaub80c2302007-11-30 20:51:32 +01003721 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003723
3724 if (strcmp(args[1], "fail") == 0) {
3725 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003726 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003727 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3728 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003731 }
3732
Willy Tarreauef6494c2010-01-28 17:12:36 +01003733 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003734 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3735 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003738 }
3739 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3740 }
3741 else {
3742 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003745 }
3746 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003747#ifdef TPROXY
3748 else if (!strcmp(args[0], "transparent")) {
3749 /* enable transparent proxy connections */
3750 curproxy->options |= PR_O_TRANSP;
3751 }
3752#endif
3753 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003754 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003756
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 if (*(args[1]) == 0) {
3758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003761 }
3762 curproxy->maxconn = atol(args[1]);
3763 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003764 else if (!strcmp(args[0], "backlog")) { /* backlog */
3765 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003767
3768 if (*(args[1]) == 0) {
3769 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003772 }
3773 curproxy->backlog = atol(args[1]);
3774 }
Willy Tarreau86034312006-12-29 00:10:33 +01003775 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003778
Willy Tarreau86034312006-12-29 00:10:33 +01003779 if (*(args[1]) == 0) {
3780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_FATAL;
3782 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003783 }
3784 curproxy->fullconn = atol(args[1]);
3785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003791 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003792 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3793 if (err) {
3794 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3795 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003798 }
3799 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
3801 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003802 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803 if (curproxy == &defproxy) {
3804 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003807 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003810
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 if (strchr(args[1], ':') == NULL) {
3812 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\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 Tarreaud5191e72010-02-09 20:50:45 +01003816 sk = str2sa(args[1]);
3817 if (!sk) {
3818 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003823 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
3825 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003829 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003830 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3831 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003836 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3838 err_code |= ERR_WARN;
3839
3840 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3841 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3842 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3843 }
3844 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3845 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3846 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3847 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003848 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3849 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3850 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3851 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003852 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003853 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003854 err_code |= ERR_ALERT | ERR_FATAL;
3855 goto out;
3856 }
3857 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003858 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003860 char *rport, *raddr;
3861 short realport = 0;
3862 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003864 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003869 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871
3872 if (!*args[2]) {
3873 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3874 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003878
3879 err = invalid_char(args[1]);
3880 if (err) {
3881 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3882 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003885 }
3886
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003887 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003888 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003889
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003890 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3891 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3892 err_code |= ERR_ALERT | ERR_ABORT;
3893 goto out;
3894 }
3895
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003896 /* the servers are linked backwards first */
3897 newsrv->next = curproxy->srv;
3898 curproxy->srv = newsrv;
3899 newsrv->proxy = curproxy;
3900 newsrv->conf.file = file;
3901 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003902
Simon Hormanaf514952011-06-21 14:34:57 +09003903 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003904 LIST_INIT(&newsrv->pendconns);
3905 do_check = 0;
3906 newsrv->state = SRV_RUNNING; /* early server setup */
3907 newsrv->last_change = now.tv_sec;
3908 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003910 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003911 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003912 * - IP: => port=+0, relative
3913 * - IP:N => port=N, absolute
3914 * - IP:+N => port=+N, relative
3915 * - IP:-N => port=-N, relative
3916 */
3917 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003918 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003919 if (rport) {
3920 *rport++ = 0;
3921 realport = atol(rport);
3922 if (!isdigit((unsigned char)*rport))
3923 newsrv->state |= SRV_MAPPORTS;
3924 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926
Willy Tarreaufab5a432011-03-04 15:31:53 +01003927 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003929 if (!sk) {
3930 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
3933 }
3934 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003935
3936 switch (newsrv->addr.ss_family) {
3937 case AF_INET:
3938 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3939 break;
3940 case AF_INET6:
3941 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3942 break;
3943 }
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
David du Colombier6f5ccb12011-03-10 22:26:24 +01004446 switch (newsrv->check_addr.ss_family) {
4447 case AF_INET:
4448 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4449 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4450 break;
4451 case AF_INET6:
4452 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4453 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4454 break;
4455 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004456
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4458 newsrv->check_port = realport; /* by default */
4459 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004460 /* not yet valid, because no port was set on
4461 * the server either. We'll check if we have
4462 * a known port on the first listener.
4463 */
4464 struct listener *l;
4465 l = curproxy->listen;
4466 if (l) {
4467 int port;
4468 port = (l->addr.ss_family == AF_INET6)
4469 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4470 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4471 newsrv->check_port = port;
4472 }
4473 }
4474 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4476 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004480
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004481 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004482 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004483 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4484 err_code |= ERR_ALERT | ERR_ABORT;
4485 goto out;
4486 }
4487
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004488 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 newsrv->state |= SRV_CHECKED;
4490 }
4491
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004492 if (!defsrv) {
4493 if (newsrv->state & SRV_BACKUP)
4494 curproxy->srv_bck++;
4495 else
4496 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004497
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004498 newsrv->prev_state = newsrv->state;
4499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 }
4501 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004502 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 int facility;
4504
4505 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4506 curproxy->logfac1 = global.logfac1;
4507 curproxy->logsrv1 = global.logsrv1;
4508 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004509 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 curproxy->logfac2 = global.logfac2;
4511 curproxy->logsrv2 = global.logsrv2;
4512 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004513 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
4515 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004516 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517
4518 facility = get_log_facility(args[2]);
4519 if (facility < 0) {
4520 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4521 exit(1);
4522 }
4523
4524 level = 7; /* max syslog level = debug */
4525 if (*(args[3])) {
4526 level = get_log_level(args[3]);
4527 if (level < 0) {
4528 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4529 exit(1);
4530 }
4531 }
4532
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004533 minlvl = 0; /* limit syslog level to this level (emerg) */
4534 if (*(args[4])) {
4535 minlvl = get_log_level(args[4]);
4536 if (level < 0) {
4537 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4538 exit(1);
4539 }
4540 }
4541
Robert Tsai81ae1952007-12-05 10:47:29 +01004542 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004543 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004544 if (!sk) {
4545 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004546 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
4549 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004550 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004551 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004552 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004553 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004554 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4555 err_code |= ERR_ALERT | ERR_FATAL;
4556 goto out;
4557 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004558 logsrv.addr = *sk;
4559 if (!get_host_port(&logsrv.addr))
4560 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562
4563 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004564 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 curproxy->logfac1 = facility;
4566 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004567 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 }
4569 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004570 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 curproxy->logfac2 = facility;
4572 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004573 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
4575 else {
4576 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 }
4581 else {
4582 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4583 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 }
4587 }
4588 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004589 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004590 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004591
Willy Tarreau977b8e42006-12-29 14:19:17 +01004592 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004594
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004596 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4597 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004601
4602 /* we must first clear any optional default setting */
4603 curproxy->options &= ~PR_O_TPXY_MASK;
4604 free(curproxy->iface_name);
4605 curproxy->iface_name = NULL;
4606 curproxy->iface_len = 0;
4607
Willy Tarreaud5191e72010-02-09 20:50:45 +01004608 sk = str2sa(args[1]);
4609 if (!sk) {
4610 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
4613 }
4614 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004615 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004616
4617 cur_arg = 2;
4618 while (*(args[cur_arg])) {
4619 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004620#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4621#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004622 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4623 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4624 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004627 }
4628#endif
4629 if (!*args[cur_arg + 1]) {
4630 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4631 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004634 }
4635
4636 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004637 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004638 curproxy->options |= PR_O_TPXY_CLI;
4639 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004640 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004641 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004642 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4643 char *name, *end;
4644
4645 name = args[cur_arg+1] + 7;
4646 while (isspace(*name))
4647 name++;
4648
4649 end = name;
4650 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4651 end++;
4652
4653 curproxy->options &= ~PR_O_TPXY_MASK;
4654 curproxy->options |= PR_O_TPXY_DYN;
4655 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4656 curproxy->bind_hdr_len = end - name;
4657 memcpy(curproxy->bind_hdr_name, name, end - name);
4658 curproxy->bind_hdr_name[end-name] = '\0';
4659 curproxy->bind_hdr_occ = -1;
4660
4661 /* now look for an occurrence number */
4662 while (isspace(*end))
4663 end++;
4664 if (*end == ',') {
4665 end++;
4666 name = end;
4667 if (*end == '-')
4668 end++;
4669 while (isdigit(*end))
4670 end++;
4671 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4672 }
4673
4674 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4675 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4676 " occurrences values smaller than %d.\n",
4677 file, linenum, MAX_HDR_HISTORY);
4678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
4680 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004681 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004682 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004683 if (!sk) {
4684 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
4688 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004689 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004690 }
4691 global.last_checks |= LSTCHK_NETADM;
4692#if !defined(CONFIG_HAP_LINUX_TPROXY)
4693 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004694#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004695#else /* no TPROXY support */
4696 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004697 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700#endif
4701 cur_arg += 2;
4702 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004703 }
4704
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4706#ifdef SO_BINDTODEVICE
4707 if (!*args[cur_arg + 1]) {
4708 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004712 }
4713 if (curproxy->iface_name)
4714 free(curproxy->iface_name);
4715
4716 curproxy->iface_name = strdup(args[cur_arg + 1]);
4717 curproxy->iface_len = strlen(curproxy->iface_name);
4718 global.last_checks |= LSTCHK_NETADM;
4719#else
4720 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4721 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004724#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004725 cur_arg += 2;
4726 continue;
4727 }
4728 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4729 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004734 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4735 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4736 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004741 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4743 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004746 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004747
4748 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4749 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004750 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004753 }
4754 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4756 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004757 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004758 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 }
4761 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4763 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004764 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 }
4768 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4770 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004771 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004774 }
4775 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4777 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004778 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004782 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4784 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004785 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004787 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004788 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004789 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4791 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004792 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004794 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004795 }
4796 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4798 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004799 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004801 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004805 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004809 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810
4811 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4812 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004813 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004816 }
4817 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4819 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004820 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004823 }
4824 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4826 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004827 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004830 }
4831 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4833 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004834 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 }
4838 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4840 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004841 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004844 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004845 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004846 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4847 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004848 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004850 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004853 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004854
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 if (curproxy == &defproxy) {
4856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004857 err_code |= ERR_ALERT | ERR_FATAL;
4858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004860 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004861 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 if (*(args[1]) == 0) {
4864 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004868
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004869 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4870 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4871 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4872 file, linenum, args[0]);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
4876 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4877 }
4878 else if (*args[2]) {
4879 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4880 file, linenum, args[0], args[2]);
4881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883 }
4884
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004885 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004886 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004887 wl->s = strdup(args[1]);
4888 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004889 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 }
4891 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004892 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004898
Willy Tarreauade5ec42010-01-28 19:33:49 +01004899 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4900 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004901 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004904 }
4905 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004906 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4907 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004908 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911 }
4912 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4914 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004915 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 }
4919 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004920 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4928 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004929 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
4933 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4935 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004936 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 }
4940 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4942 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004943 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004948 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004949
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 if (curproxy == &defproxy) {
4951 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004952 err_code |= ERR_ALERT | ERR_FATAL;
4953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004955 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 if (*(args[1]) == 0) {
4959 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004964 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4965 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4966 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4967 file, linenum, args[0]);
4968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
4970 }
4971 err_code |= warnif_cond_requires_req(cond, file, linenum);
4972 }
4973 else if (*args[2]) {
4974 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4975 file, linenum, args[0], args[2]);
4976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
4978 }
4979
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004980 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004981 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004982 wl->s = strdup(args[1]);
4983 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 }
4985 else if (!strcmp(args[0], "errorloc") ||
4986 !strcmp(args[0], "errorloc302") ||
4987 !strcmp(args[0], "errorloc303")) { /* error location */
4988 int errnum, errlen;
4989 char *err;
4990
Willy Tarreau977b8e42006-12-29 14:19:17 +01004991 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004993
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004995 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
4999
5000 errnum = atol(args[1]);
5001 if (!strcmp(args[0], "errorloc303")) {
5002 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5003 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5004 } else {
5005 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5006 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5007 }
5008
Willy Tarreau0f772532006-12-23 20:51:41 +01005009 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5010 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005011 chunk_destroy(&curproxy->errmsg[rc]);
5012 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005013 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005016
5017 if (rc >= HTTP_ERR_SIZE) {
5018 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5019 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 free(err);
5021 }
5022 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005023 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5024 int errnum, errlen, fd;
5025 char *err;
5026 struct stat stat;
5027
5028 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005029 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005030
5031 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005032 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005035 }
5036
5037 fd = open(args[2], O_RDONLY);
5038 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5039 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5040 file, linenum, args[2], args[1]);
5041 if (fd >= 0)
5042 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005045 }
5046
Willy Tarreau27a674e2009-08-17 07:23:33 +02005047 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005048 errlen = stat.st_size;
5049 } else {
5050 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005051 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005052 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005053 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005054 }
5055
5056 err = malloc(errlen); /* malloc() must succeed during parsing */
5057 errnum = read(fd, err, errlen);
5058 if (errnum != errlen) {
5059 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5060 file, linenum, args[2], args[1]);
5061 close(fd);
5062 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005065 }
5066 close(fd);
5067
5068 errnum = atol(args[1]);
5069 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5070 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005071 chunk_destroy(&curproxy->errmsg[rc]);
5072 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005073 break;
5074 }
5075 }
5076
5077 if (rc >= HTTP_ERR_SIZE) {
5078 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5079 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005081 free(err);
5082 }
5083 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005084 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005085 struct cfg_kw_list *kwl;
5086 int index;
5087
5088 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5089 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5090 if (kwl->kw[index].section != CFG_LISTEN)
5091 continue;
5092 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5093 /* prepare error message just in case */
5094 snprintf(trash, sizeof(trash),
5095 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005096 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5097 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005098 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005101 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005102 else if (rc > 0) {
5103 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_WARN;
5105 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005106 }
Willy Tarreau93893792009-07-23 13:19:11 +02005107 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005108 }
5109 }
5110 }
5111
Willy Tarreau6daf3432008-01-22 16:44:08 +01005112 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 }
Willy Tarreau93893792009-07-23 13:19:11 +02005116 out:
5117 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118}
5119
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005120int
5121cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5122{
5123
5124 int err_code = 0;
5125 const char *err;
5126
5127 if (!strcmp(args[0], "userlist")) { /* new userlist */
5128 struct userlist *newul;
5129
5130 if (!*args[1]) {
5131 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5132 file, linenum, args[0]);
5133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
5135 }
5136
5137 err = invalid_char(args[1]);
5138 if (err) {
5139 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5140 file, linenum, *err, args[0], args[1]);
5141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
5143 }
5144
5145 for (newul = userlist; newul; newul = newul->next)
5146 if (!strcmp(newul->name, args[1])) {
5147 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5148 file, linenum, args[1]);
5149 err_code |= ERR_WARN;
5150 goto out;
5151 }
5152
5153 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5154 if (!newul) {
5155 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5156 err_code |= ERR_ALERT | ERR_ABORT;
5157 goto out;
5158 }
5159
5160 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5161 newul->name = strdup(args[1]);
5162
5163 if (!newul->groupusers | !newul->name) {
5164 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5165 err_code |= ERR_ALERT | ERR_ABORT;
5166 goto out;
5167 }
5168
5169 newul->next = userlist;
5170 userlist = newul;
5171
5172 } else if (!strcmp(args[0], "group")) { /* new group */
5173 int cur_arg, i;
5174 const char *err;
5175
5176 if (!*args[1]) {
5177 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5178 file, linenum, args[0]);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182
5183 err = invalid_char(args[1]);
5184 if (err) {
5185 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5186 file, linenum, *err, args[0], args[1]);
5187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
5189 }
5190
5191 for(i = 0; i < userlist->grpcnt; i++)
5192 if (!strcmp(userlist->groups[i], args[1])) {
5193 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5194 file, linenum, args[1], userlist->name);
5195 err_code |= ERR_ALERT;
5196 goto out;
5197 }
5198
5199 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5200 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5201 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
5206 cur_arg = 2;
5207
5208 while (*args[cur_arg]) {
5209 if (!strcmp(args[cur_arg], "users")) {
5210 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5211 cur_arg += 2;
5212 continue;
5213 } else {
5214 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5215 file, linenum, args[0]);
5216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219 }
5220
5221 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5222 } else if (!strcmp(args[0], "user")) { /* new user */
5223 struct auth_users *newuser;
5224 int cur_arg;
5225
5226 if (!*args[1]) {
5227 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5228 file, linenum, args[0]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 }
5232
5233 for (newuser = userlist->users; newuser; newuser = newuser->next)
5234 if (!strcmp(newuser->user, args[1])) {
5235 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5236 file, linenum, args[1], userlist->name);
5237 err_code |= ERR_ALERT;
5238 goto out;
5239 }
5240
5241 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5242 if (!newuser) {
5243 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5244 err_code |= ERR_ALERT | ERR_ABORT;
5245 goto out;
5246 }
5247
5248 newuser->user = strdup(args[1]);
5249
5250 newuser->next = userlist->users;
5251 userlist->users = newuser;
5252
5253 cur_arg = 2;
5254
5255 while (*args[cur_arg]) {
5256 if (!strcmp(args[cur_arg], "password")) {
5257#ifndef CONFIG_HAP_CRYPT
5258 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5259 file, linenum);
5260 err_code |= ERR_ALERT;
5261#endif
5262 newuser->pass = strdup(args[cur_arg + 1]);
5263 cur_arg += 2;
5264 continue;
5265 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5266 newuser->pass = strdup(args[cur_arg + 1]);
5267 newuser->flags |= AU_O_INSECURE;
5268 cur_arg += 2;
5269 continue;
5270 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005271 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005272 cur_arg += 2;
5273 continue;
5274 } else {
5275 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5276 file, linenum, args[0]);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280 }
5281 } else {
5282 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5283 err_code |= ERR_ALERT | ERR_FATAL;
5284 }
5285
5286out:
5287 return err_code;
5288}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289
5290/*
5291 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005292 * Returns the error code, 0 if OK, or any combination of :
5293 * - ERR_ABORT: must abort ASAP
5294 * - ERR_FATAL: we can continue parsing but not start the service
5295 * - ERR_WARN: a warning has been emitted
5296 * - ERR_ALERT: an alert has been emitted
5297 * Only the two first ones can stop processing, the two others are just
5298 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005300int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005302 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005303 FILE *f;
5304 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005306 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if ((f=fopen(file,"r")) == NULL)
5309 return -1;
5310
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005311 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005312 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005313 char *end;
5314 char *args[MAX_LINE_ARGS + 1];
5315 char *line = thisline;
5316
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317 linenum++;
5318
5319 end = line + strlen(line);
5320
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005321 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5322 /* Check if we reached the limit and the last char is not \n.
5323 * Watch out for the last line without the terminating '\n'!
5324 */
5325 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005326 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005327 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005328 }
5329
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005331 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 line++;
5333
5334 arg = 0;
5335 args[arg] = line;
5336
5337 while (*line && arg < MAX_LINE_ARGS) {
5338 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5339 * C equivalent value. Other combinations left unchanged (eg: \1).
5340 */
5341 if (*line == '\\') {
5342 int skip = 0;
5343 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5344 *line = line[1];
5345 skip = 1;
5346 }
5347 else if (line[1] == 'r') {
5348 *line = '\r';
5349 skip = 1;
5350 }
5351 else if (line[1] == 'n') {
5352 *line = '\n';
5353 skip = 1;
5354 }
5355 else if (line[1] == 't') {
5356 *line = '\t';
5357 skip = 1;
5358 }
5359 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005360 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 unsigned char hex1, hex2;
5362 hex1 = toupper(line[2]) - '0';
5363 hex2 = toupper(line[3]) - '0';
5364 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5365 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5366 *line = (hex1<<4) + hex2;
5367 skip = 3;
5368 }
5369 else {
5370 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005371 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 }
5374 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005375 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 end -= skip;
5377 }
5378 line++;
5379 }
5380 else if (*line == '#' || *line == '\n' || *line == '\r') {
5381 /* end of string, end of loop */
5382 *line = 0;
5383 break;
5384 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005385 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005387 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005388 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 line++;
5390 args[++arg] = line;
5391 }
5392 else {
5393 line++;
5394 }
5395 }
5396
5397 /* empty line */
5398 if (!**args)
5399 continue;
5400
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005401 if (*line) {
5402 /* we had to stop due to too many args.
5403 * Let's terminate the string, print the offending part then cut the
5404 * last arg.
5405 */
5406 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5407 line++;
5408 *line = '\0';
5409
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005410 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005411 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005412 err_code |= ERR_ALERT | ERR_FATAL;
5413 args[arg] = line;
5414 }
5415
Willy Tarreau540abe42007-05-02 20:50:16 +02005416 /* zero out remaining args and ensure that at least one entry
5417 * is zeroed out.
5418 */
5419 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 args[arg] = line;
5421 }
5422
Willy Tarreau3842f002009-06-14 11:39:52 +02005423 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005424 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005425 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005426 for (arg=0; *args[arg+1]; arg++)
5427 args[arg] = args[arg+1]; // shift args after inversion
5428 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005429 else if (!strcmp(args[0], "default")) {
5430 kwm = KWM_DEF;
5431 for (arg=0; *args[arg+1]; arg++)
5432 args[arg] = args[arg+1]; // shift args after inversion
5433 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005434
Willy Tarreau3842f002009-06-14 11:39:52 +02005435 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5436 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005437 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005438 }
5439
Willy Tarreau977b8e42006-12-29 14:19:17 +01005440 if (!strcmp(args[0], "listen") ||
5441 !strcmp(args[0], "frontend") ||
5442 !strcmp(args[0], "backend") ||
5443 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005444 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005445 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005446 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005447 cursection = strdup(args[0]);
5448 }
5449 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005451 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005452 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005453 }
5454 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005455 confsect = CFG_USERLIST;
5456 free(cursection);
5457 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005458 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005459 else if (!strcmp(args[0], "peers")) {
5460 confsect = CFG_PEERS;
5461 free(cursection);
5462 cursection = strdup(args[0]);
5463 }
5464
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 /* else it's a section keyword */
5466
5467 switch (confsect) {
5468 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 break;
5471 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005472 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005474 case CFG_USERLIST:
5475 err_code |= cfg_parse_users(file, linenum, args, kwm);
5476 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005477 case CFG_PEERS:
5478 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5479 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005481 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005484
5485 if (err_code & ERR_ABORT)
5486 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005488 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005489 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005491 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005492}
5493
Willy Tarreaubb925012009-07-23 13:36:36 +02005494/*
5495 * Returns the error code, 0 if OK, or any combination of :
5496 * - ERR_ABORT: must abort ASAP
5497 * - ERR_FATAL: we can continue parsing but not start the service
5498 * - ERR_WARN: a warning has been emitted
5499 * - ERR_ALERT: an alert has been emitted
5500 * Only the two first ones can stop processing, the two others are just
5501 * indicators.
5502 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005503int check_config_validity()
5504{
5505 int cfgerr = 0;
5506 struct proxy *curproxy = NULL;
5507 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005508 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005509 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005510 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511
5512 /*
5513 * Now, check for the integrity of all that we have collected.
5514 */
5515
5516 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005517 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005519 /* first, we will invert the proxy list order */
5520 curproxy = NULL;
5521 while (proxy) {
5522 struct proxy *next;
5523
5524 next = proxy->next;
5525 proxy->next = curproxy;
5526 curproxy = proxy;
5527 if (!next)
5528 break;
5529 proxy = next;
5530 }
5531
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005533 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
5537
5538 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005539 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005540 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005541 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005542 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005543 unsigned int next_id;
5544
5545 if (!curproxy->uuid) {
5546 /* proxy ID not set, use automatic numbering with first
5547 * spare entry starting with next_pxid.
5548 */
5549 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5550 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5551 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005552 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005553 next_pxid++;
5554
Willy Tarreau55ea7572007-06-17 19:56:27 +02005555
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005557 /* ensure we don't keep listeners uselessly bound */
5558 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 curproxy = curproxy->next;
5560 continue;
5561 }
5562
Willy Tarreauff01a212009-03-15 13:46:16 +01005563 switch (curproxy->mode) {
5564 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005565 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005566 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005567 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5568 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005569 cfgerr++;
5570 }
5571
5572 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005573 Warning("config : servers will be ignored for %s '%s'.\n",
5574 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005575 break;
5576
5577 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005578 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 break;
5580
5581 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005582 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005583 break;
5584 }
5585
5586 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005587 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5588 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 cfgerr++;
5590 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005591
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005592 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005593 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005594 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005595 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5596 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 cfgerr++;
5598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005601 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5602 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005603 cfgerr++;
5604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005606 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005607 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5608 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005609 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005610 }
5611 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005612 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005613 /* If no LB algo is set in a backend, and we're not in
5614 * transparent mode, dispatch mode nor proxy mode, we
5615 * want to use balance roundrobin by default.
5616 */
5617 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5618 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 }
5620 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005621
Willy Tarreau1620ec32011-08-06 17:05:02 +02005622 if (curproxy->options & PR_O_DISPATCH)
5623 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5624 else if (curproxy->options & PR_O_HTTP_PROXY)
5625 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5626 else if (curproxy->options & PR_O_TRANSP)
5627 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005628
Willy Tarreau1620ec32011-08-06 17:05:02 +02005629 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5630 if (curproxy->options & PR_O_DISABLE404) {
5631 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5632 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5633 err_code |= ERR_WARN;
5634 curproxy->options &= ~PR_O_DISABLE404;
5635 }
5636 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5637 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5638 "send-state", proxy_type_str(curproxy), curproxy->id);
5639 err_code |= ERR_WARN;
5640 curproxy->options &= ~PR_O2_CHK_SNDST;
5641 }
Willy Tarreauef781042010-01-27 11:53:01 +01005642 }
5643
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005644 /* if a default backend was specified, let's find it */
5645 if (curproxy->defbe.name) {
5646 struct proxy *target;
5647
Alex Williams96532db2009-11-01 21:27:13 -05005648 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005649 if (!target) {
5650 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5651 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005652 cfgerr++;
5653 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005654 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5655 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005656 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005657 } else {
5658 free(curproxy->defbe.name);
5659 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005660 /* we force the backend to be present on at least all of
5661 * the frontend's processes.
5662 */
5663 target->bind_proc = curproxy->bind_proc ?
5664 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
5666 }
5667
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005668 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005669 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5670 /* map jump target for ACT_SETBE in req_rep chain */
5671 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005672 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005673 struct proxy *target;
5674
Willy Tarreaua496b602006-12-17 23:15:24 +01005675 if (exp->action != ACT_SETBE)
5676 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005677
Alex Williams96532db2009-11-01 21:27:13 -05005678 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005679 if (!target) {
5680 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5681 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005682 cfgerr++;
5683 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005684 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5685 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005686 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005687 } else {
5688 free((void *)exp->replace);
5689 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005690 /* we force the backend to be present on at least all of
5691 * the frontend's processes.
5692 */
5693 target->bind_proc = curproxy->bind_proc ?
5694 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005695 }
5696 }
5697 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005698
5699 /* find the target proxy for 'use_backend' rules */
5700 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005701 struct proxy *target;
5702
Alex Williams96532db2009-11-01 21:27:13 -05005703 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005704
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005705 if (!target) {
5706 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5707 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005708 cfgerr++;
5709 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005710 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5711 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005712 cfgerr++;
5713 } else {
5714 free((void *)rule->be.name);
5715 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005716 /* we force the backend to be present on at least all of
5717 * the frontend's processes.
5718 */
5719 target->bind_proc = curproxy->bind_proc ?
5720 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005721 }
5722 }
5723
Emeric Brunb982a3d2010-01-04 15:45:53 +01005724 /* find the target table for 'stick' rules */
5725 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5726 struct proxy *target;
5727
Emeric Brun1d33b292010-01-04 15:47:17 +01005728 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5729 if (mrule->flags & STK_IS_STORE)
5730 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5731
Emeric Brunb982a3d2010-01-04 15:45:53 +01005732 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005733 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005734 else
5735 target = curproxy;
5736
5737 if (!target) {
5738 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5739 curproxy->id, mrule->table.name);
5740 cfgerr++;
5741 }
5742 else if (target->table.size == 0) {
5743 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5744 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5745 cfgerr++;
5746 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005747 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005748 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5749 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5750 cfgerr++;
5751 }
5752 else {
5753 free((void *)mrule->table.name);
5754 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005755 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005756 }
5757 }
5758
5759 /* find the target table for 'store response' rules */
5760 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5761 struct proxy *target;
5762
Emeric Brun1d33b292010-01-04 15:47:17 +01005763 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5764
Emeric Brunb982a3d2010-01-04 15:45:53 +01005765 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005766 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005767 else
5768 target = curproxy;
5769
5770 if (!target) {
5771 Alert("Proxy '%s': unable to find store table '%s'.\n",
5772 curproxy->id, mrule->table.name);
5773 cfgerr++;
5774 }
5775 else if (target->table.size == 0) {
5776 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5777 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5778 cfgerr++;
5779 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005780 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005781 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5782 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5783 cfgerr++;
5784 }
5785 else {
5786 free((void *)mrule->table.name);
5787 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005788 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005789 }
5790 }
5791
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005792 /* find the target table for 'tcp-request' layer 4 rules */
5793 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5794 struct proxy *target;
5795
Willy Tarreau56123282010-08-06 19:06:56 +02005796 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005797 continue;
5798
5799 if (trule->act_prm.trk_ctr.table.n)
5800 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5801 else
5802 target = curproxy;
5803
5804 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005805 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5806 curproxy->id, trule->act_prm.trk_ctr.table.n,
5807 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005808 cfgerr++;
5809 }
5810 else if (target->table.size == 0) {
5811 Alert("Proxy '%s': table '%s' used but not configured.\n",
5812 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5813 cfgerr++;
5814 }
5815 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005816 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 +02005817 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5818 cfgerr++;
5819 }
5820 else {
5821 free(trule->act_prm.trk_ctr.table.n);
5822 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005823 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005824 * to pass a list of counters to track and allocate them right here using
5825 * stktable_alloc_data_type().
5826 */
5827 }
5828 }
5829
Willy Tarreaud1f96522010-08-03 19:34:32 +02005830 /* find the target table for 'tcp-request' layer 6 rules */
5831 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5832 struct proxy *target;
5833
Willy Tarreau56123282010-08-06 19:06:56 +02005834 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005835 continue;
5836
5837 if (trule->act_prm.trk_ctr.table.n)
5838 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5839 else
5840 target = curproxy;
5841
5842 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005843 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5844 curproxy->id, trule->act_prm.trk_ctr.table.n,
5845 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005846 cfgerr++;
5847 }
5848 else if (target->table.size == 0) {
5849 Alert("Proxy '%s': table '%s' used but not configured.\n",
5850 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5851 cfgerr++;
5852 }
5853 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005854 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 +02005855 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5856 cfgerr++;
5857 }
5858 else {
5859 free(trule->act_prm.trk_ctr.table.n);
5860 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005861 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005862 * to pass a list of counters to track and allocate them right here using
5863 * stktable_alloc_data_type().
5864 */
5865 }
5866 }
5867
Emeric Brun32da3c42010-09-23 18:39:19 +02005868 if (curproxy->table.peers.name) {
5869 struct peers *curpeers = peers;
5870
5871 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5872 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5873 free((void *)curproxy->table.peers.name);
5874 curproxy->table.peers.p = peers;
5875 break;
5876 }
5877 }
5878
5879 if (!curpeers) {
5880 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5881 curproxy->id, curproxy->table.peers.name);
5882 cfgerr++;
5883 }
5884 else if (!curpeers->peers_fe) {
5885 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5886 curproxy->id, curpeers->id);
5887 cfgerr++;
5888 }
5889 }
5890
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005891 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005892 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005893 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5894 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5895 "proxy", curproxy->id);
5896 cfgerr++;
5897 goto out_uri_auth_compat;
5898 }
5899
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005900 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005901 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005902 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005903 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005904
Willy Tarreau95fa4692010-02-01 13:05:50 +01005905 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5906 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005907
5908 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005909 uri_auth_compat_req[i++] = "realm";
5910 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5911 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005912
Willy Tarreau95fa4692010-02-01 13:05:50 +01005913 uri_auth_compat_req[i++] = "unless";
5914 uri_auth_compat_req[i++] = "{";
5915 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5916 uri_auth_compat_req[i++] = "}";
5917 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005918
Willy Tarreauff011f22011-01-06 17:51:27 +01005919 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5920 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005921 cfgerr++;
5922 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005923 }
5924
Willy Tarreauff011f22011-01-06 17:51:27 +01005925 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005926
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005927 if (curproxy->uri_auth->auth_realm) {
5928 free(curproxy->uri_auth->auth_realm);
5929 curproxy->uri_auth->auth_realm = NULL;
5930 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005931
5932 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005933 }
5934out_uri_auth_compat:
5935
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005936 cfgerr += acl_find_targets(curproxy);
5937
Willy Tarreau2738a142006-07-08 17:28:09 +02005938 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005939 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005940 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005941 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005942 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005943 " | While not properly invalid, you will certainly encounter various problems\n"
5944 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005945 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005946 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005947 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005948 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005949
Willy Tarreau1fa31262007-12-03 00:36:16 +01005950 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5951 * We must still support older configurations, so let's find out whether those
5952 * parameters have been set or must be copied from contimeouts.
5953 */
5954 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005955 if (!curproxy->timeout.tarpit ||
5956 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005957 /* tarpit timeout not set. We search in the following order:
5958 * default.tarpit, curr.connect, default.connect.
5959 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005960 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005961 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005962 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005963 curproxy->timeout.tarpit = 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.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005966 }
5967 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005968 (!curproxy->timeout.queue ||
5969 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005970 /* queue timeout not set. We search in the following order:
5971 * default.queue, curr.connect, default.connect.
5972 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005974 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005975 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005976 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005977 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005978 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005979 }
5980 }
5981
Willy Tarreau1620ec32011-08-06 17:05:02 +02005982 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005983 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5984 curproxy->check_req = (char *)malloc(curproxy->check_len);
5985 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005986 }
5987
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005988 /* The small pools required for the capture lists */
5989 if (curproxy->nb_req_cap)
5990 curproxy->req_cap_pool = create_pool("ptrcap",
5991 curproxy->nb_req_cap * sizeof(char *),
5992 MEM_F_SHARED);
5993 if (curproxy->nb_rsp_cap)
5994 curproxy->rsp_cap_pool = create_pool("ptrcap",
5995 curproxy->nb_rsp_cap * sizeof(char *),
5996 MEM_F_SHARED);
5997
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005998 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5999 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6000 MEM_F_SHARED);
6001
Willy Tarreaubaaee002006-06-26 02:48:02 +02006002 /* first, we will invert the servers list order */
6003 newsrv = NULL;
6004 while (curproxy->srv) {
6005 struct server *next;
6006
6007 next = curproxy->srv->next;
6008 curproxy->srv->next = newsrv;
6009 newsrv = curproxy->srv;
6010 if (!next)
6011 break;
6012 curproxy->srv = next;
6013 }
6014
Willy Tarreaudd701652010-05-25 23:03:02 +02006015 /* assign automatic UIDs to servers which don't have one yet */
6016 next_id = 1;
6017 newsrv = curproxy->srv;
6018 while (newsrv != NULL) {
6019 if (!newsrv->puid) {
6020 /* server ID not set, use automatic numbering with first
6021 * spare entry starting with next_svid.
6022 */
6023 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6024 newsrv->conf.id.key = newsrv->puid = next_id;
6025 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6026 }
6027 next_id++;
6028 newsrv = newsrv->next;
6029 }
6030
Willy Tarreau20697042007-11-15 23:26:18 +01006031 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006032 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006034 /* We have to initialize the server lookup mechanism depending
6035 * on what LB algorithm was choosen.
6036 */
6037
6038 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6039 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6040 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006041 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6042 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6043 init_server_map(curproxy);
6044 } else {
6045 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6046 fwrr_init_server_groups(curproxy);
6047 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006048 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006049
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006050 case BE_LB_KIND_LC:
6051 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006052 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006053 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006054
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006055 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006056 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6057 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6058 chash_init_server_tree(curproxy);
6059 } else {
6060 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6061 init_server_map(curproxy);
6062 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006063 break;
6064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006065
6066 if (curproxy->options & PR_O_LOGASAP)
6067 curproxy->to_log &= ~LW_BYTES;
6068
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006069 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6070 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6071 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6072 proxy_type_str(curproxy), curproxy->id);
6073 err_code |= ERR_WARN;
6074 }
6075
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006076 if (curproxy->mode != PR_MODE_HTTP) {
6077 int optnum;
6078
6079 if (curproxy->options & PR_O_COOK_ANY) {
6080 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6081 proxy_type_str(curproxy), curproxy->id);
6082 err_code |= ERR_WARN;
6083 }
6084
6085 if (curproxy->uri_auth) {
6086 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6087 proxy_type_str(curproxy), curproxy->id);
6088 err_code |= ERR_WARN;
6089 curproxy->uri_auth = NULL;
6090 }
6091
6092 if (curproxy->options & PR_O_FWDFOR) {
6093 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6094 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6095 err_code |= ERR_WARN;
6096 curproxy->options &= ~PR_O_FWDFOR;
6097 }
6098
6099 if (curproxy->options & PR_O_ORGTO) {
6100 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6101 "originalto", proxy_type_str(curproxy), curproxy->id);
6102 err_code |= ERR_WARN;
6103 curproxy->options &= ~PR_O_ORGTO;
6104 }
6105
6106 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6107 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6108 (curproxy->cap & cfg_opts[optnum].cap) &&
6109 (curproxy->options & cfg_opts[optnum].val)) {
6110 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6111 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6112 err_code |= ERR_WARN;
6113 curproxy->options &= ~cfg_opts[optnum].val;
6114 }
6115 }
6116
6117 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6118 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6119 (curproxy->cap & cfg_opts2[optnum].cap) &&
6120 (curproxy->options2 & cfg_opts2[optnum].val)) {
6121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6122 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options2 &= ~cfg_opts2[optnum].val;
6125 }
6126 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006127
Willy Tarreauefa5f512010-03-30 20:13:29 +02006128#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006129 if (curproxy->bind_hdr_occ) {
6130 curproxy->bind_hdr_occ = 0;
6131 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6132 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6133 err_code |= ERR_WARN;
6134 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006135#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006136 }
6137
Willy Tarreaubaaee002006-06-26 02:48:02 +02006138 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006139 * ensure that we're not cross-dressing a TCP server into HTTP.
6140 */
6141 newsrv = curproxy->srv;
6142 while (newsrv != NULL) {
6143 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006144 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6145 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006146 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006147 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006148
Willy Tarreauefa5f512010-03-30 20:13:29 +02006149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006150 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6151 newsrv->bind_hdr_occ = 0;
6152 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6153 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6154 err_code |= ERR_WARN;
6155 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006156#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006157 newsrv = newsrv->next;
6158 }
6159
6160 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 * If this server supports a maxconn parameter, it needs a dedicated
6162 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006163 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 */
6165 newsrv = curproxy->srv;
6166 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006167 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006168 /* Only 'minconn' was specified, or it was higher than or equal
6169 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6170 * this will avoid further useless expensive computations.
6171 */
6172 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006173 } else if (newsrv->maxconn && !newsrv->minconn) {
6174 /* minconn was not specified, so we set it to maxconn */
6175 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 }
6177
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006178 if (newsrv->trackit) {
6179 struct proxy *px;
6180 struct server *srv;
6181 char *pname, *sname;
6182
6183 pname = newsrv->trackit;
6184 sname = strrchr(pname, '/');
6185
6186 if (sname)
6187 *sname++ = '\0';
6188 else {
6189 sname = pname;
6190 pname = NULL;
6191 }
6192
6193 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006194 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006195 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006196 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6197 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006198 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006199 cfgerr++;
6200 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006201 }
6202 } else
6203 px = curproxy;
6204
6205 srv = findserver(px, sname);
6206 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006207 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6208 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006209 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006210 cfgerr++;
6211 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006212 }
6213
6214 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006215 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006216 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006217 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006218 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006219 cfgerr++;
6220 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006221 }
6222
6223 if (curproxy != px &&
6224 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006225 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006226 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006227 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006229 cfgerr++;
6230 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006231 }
6232
6233 newsrv->tracked = srv;
6234 newsrv->tracknext = srv->tracknext;
6235 srv->tracknext = newsrv;
6236
6237 free(newsrv->trackit);
6238 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006239 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006240 newsrv = newsrv->next;
6241 }
6242
Willy Tarreauc1a21672009-08-16 22:37:44 +02006243 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006244 curproxy->accept = frontend_accept;
6245
Willy Tarreauc1a21672009-08-16 22:37:44 +02006246 if (curproxy->tcp_req.inspect_delay ||
6247 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006248 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006249
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006250 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006251 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006252 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006253 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006254
6255 /* both TCP and HTTP must check switching rules */
6256 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6257 }
6258
6259 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006260 if (curproxy->tcp_req.inspect_delay ||
6261 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6262 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6263
Emeric Brun97679e72010-09-23 17:56:44 +02006264 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6265 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6266
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006267 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006268 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006269 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006270 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006271
6272 /* If the backend does requires RDP cookie persistence, we have to
6273 * enable the corresponding analyser.
6274 */
6275 if (curproxy->options2 & PR_O2_RDPC_PRST)
6276 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6277 }
6278
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006279 listener = NULL;
6280 while (curproxy->listen) {
6281 struct listener *next;
6282
6283 next = curproxy->listen->next;
6284 curproxy->listen->next = listener;
6285 listener = curproxy->listen;
6286
6287 if (!next)
6288 break;
6289
6290 curproxy->listen = next;
6291 }
6292
Willy Tarreaue6b98942007-10-29 01:09:36 +01006293 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006294 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006295 listener = curproxy->listen;
6296 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006297 if (!listener->luid) {
6298 /* listener ID not set, use automatic numbering with first
6299 * spare entry starting with next_luid.
6300 */
6301 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6302 listener->conf.id.key = listener->luid = next_id;
6303 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006304 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006305 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006306
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006307 /* enable separate counters */
6308 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6309 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6310 if (!listener->name) {
6311 sprintf(trash, "sock-%d", listener->luid);
6312 listener->name = strdup(trash);
6313 }
6314 }
6315
Willy Tarreaue6b98942007-10-29 01:09:36 +01006316 if (curproxy->options & PR_O_TCP_NOLING)
6317 listener->options |= LI_O_NOLINGER;
6318 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006319 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006320 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006321 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006322 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006323 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006324 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006325
Willy Tarreau8a956912010-10-15 14:27:08 +02006326 if (listener->options & LI_O_ACC_PROXY)
6327 listener->analysers |= AN_REQ_DECODE_PROXY;
6328
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006329 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6330 listener->options |= LI_O_TCP_RULES;
6331
Willy Tarreaude3041d2010-05-31 10:56:17 +02006332 if (curproxy->mon_mask.s_addr)
6333 listener->options |= LI_O_CHK_MONNET;
6334
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006335 /* smart accept mode is automatic in HTTP mode */
6336 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6337 (curproxy->mode == PR_MODE_HTTP &&
6338 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6339 listener->options |= LI_O_NOQUICKACK;
6340
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006341 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006342 listener = listener->next;
6343 }
6344
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006345 /* Check multi-process mode compatibility for the current proxy */
6346 if (global.nbproc > 1) {
6347 int nbproc = 0;
6348 if (curproxy->bind_proc) {
6349 int proc;
6350 for (proc = 0; proc < global.nbproc; proc++) {
6351 if (curproxy->bind_proc & (1 << proc)) {
6352 nbproc++;
6353 }
6354 }
6355 } else {
6356 nbproc = global.nbproc;
6357 }
6358 if (curproxy->table.peers.name) {
6359 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6360 curproxy->id);
6361 cfgerr++;
6362 }
6363 if (nbproc > 1) {
6364 if (curproxy->uri_auth) {
6365 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6366 curproxy->id);
6367 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6368 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6369 curproxy->id);
6370 }
6371 }
6372 if (curproxy->appsession_name) {
6373 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6374 curproxy->id);
6375 }
6376 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6377 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6378 curproxy->id);
6379 }
6380 }
6381 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006382
6383 /* create the task associated with the proxy */
6384 curproxy->task = task_new();
6385 if (curproxy->task) {
6386 curproxy->task->context = curproxy;
6387 curproxy->task->process = manage_proxy;
6388 /* no need to queue, it will be done automatically if some
6389 * listener gets limited.
6390 */
6391 curproxy->task->expire = TICK_ETERNITY;
6392 } else {
6393 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6394 curproxy->id);
6395 cfgerr++;
6396 }
6397
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 curproxy = curproxy->next;
6399 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006400
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006401 /* Check multi-process mode compatibility */
6402 if (global.nbproc > 1) {
6403 if (global.stats_fe) {
6404 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6405 }
6406 }
6407
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006408 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6409 struct auth_users *curuser;
6410 int g;
6411
6412 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6413 unsigned int group_mask = 0;
6414 char *group = NULL;
6415
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006416 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006417 continue;
6418
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006419 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006420
6421 for (g = 0; g < curuserlist->grpcnt; g++)
6422 if (!strcmp(curuserlist->groups[g], group))
6423 break;
6424
6425 if (g == curuserlist->grpcnt) {
6426 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6427 curuserlist->name, group, curuser->user);
6428 err_code |= ERR_ALERT | ERR_FATAL;
6429 goto out;
6430 }
6431
6432 group_mask |= (1 << g);
6433 }
6434
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006435 free(curuser->u.groups);
6436 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006437 }
6438
6439 for (g = 0; g < curuserlist->grpcnt; g++) {
6440 char *user = NULL;
6441
6442 if (!curuserlist->groupusers[g])
6443 continue;
6444
6445 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6446 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6447 if (!strcmp(curuser->user, user))
6448 break;
6449
6450 if (!curuser) {
6451 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6452 curuserlist->name, user, curuserlist->groups[g]);
6453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
6455 }
6456
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006457 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006458 }
6459
6460 free(curuserlist->groupusers[g]);
6461 }
6462
6463 free(curuserlist->groupusers);
6464
6465#ifdef DEBUG_AUTH
6466 for (g = 0; g < curuserlist->grpcnt; g++) {
6467 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6468
6469 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6470 if (curuser->group_mask & (1 << g))
6471 fprintf(stderr, " %s", curuser->user);
6472 }
6473
6474 fprintf(stderr, "\n");
6475 }
6476#endif
6477
Willy Tarreaufbb78422011-06-05 15:38:35 +02006478 }
6479
6480 /* automatically compute fullconn if not set. We must not do it in the
6481 * loop above because cross-references are not yet fully resolved.
6482 */
6483 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6484 /* If <fullconn> is not set, let's set it to 10% of the sum of
6485 * the possible incoming frontend's maxconns.
6486 */
6487 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6488 struct proxy *fe;
6489 int total = 0;
6490
6491 /* sum up the number of maxconns of frontends which
6492 * reference this backend at least once or which are
6493 * the same one ('listen').
6494 */
6495 for (fe = proxy; fe; fe = fe->next) {
6496 struct switching_rule *rule;
6497 struct hdr_exp *exp;
6498 int found = 0;
6499
6500 if (!(fe->cap & PR_CAP_FE))
6501 continue;
6502
6503 if (fe == curproxy) /* we're on a "listen" instance */
6504 found = 1;
6505
6506 if (fe->defbe.be == curproxy) /* "default_backend" */
6507 found = 1;
6508
6509 /* check if a "use_backend" rule matches */
6510 if (!found) {
6511 list_for_each_entry(rule, &fe->switching_rules, list) {
6512 if (rule->be.backend == curproxy) {
6513 found = 1;
6514 break;
6515 }
6516 }
6517 }
6518
6519 /* check if a "reqsetbe" rule matches */
6520 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6521 if (exp->action == ACT_SETBE &&
6522 (struct proxy *)exp->replace == curproxy) {
6523 found = 1;
6524 break;
6525 }
6526 }
6527
6528 /* now we've checked all possible ways to reference a backend
6529 * from a frontend.
6530 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006531 if (!found)
6532 continue;
6533 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006534 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006535 /* we have the sum of the maxconns in <total>. We only
6536 * keep 10% of that sum to set the default fullconn, with
6537 * a hard minimum of 1 (to avoid a divide by zero).
6538 */
6539 curproxy->fullconn = (total + 9) / 10;
6540 if (!curproxy->fullconn)
6541 curproxy->fullconn = 1;
6542 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006543 }
6544
Willy Tarreau056f5682010-06-06 15:51:11 +02006545 /* initialize stick-tables on backend capable proxies. This must not
6546 * be done earlier because the data size may be discovered while parsing
6547 * other proxies.
6548 */
6549 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006550 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006551
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006552 /*
6553 * Recount currently required checks.
6554 */
6555
6556 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6557 int optnum;
6558
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006559 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6560 if (curproxy->options & cfg_opts[optnum].val)
6561 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006562
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006563 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6564 if (curproxy->options2 & cfg_opts2[optnum].val)
6565 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006566 }
6567
Willy Tarreaubb925012009-07-23 13:36:36 +02006568 if (cfgerr > 0)
6569 err_code |= ERR_ALERT | ERR_FATAL;
6570 out:
6571 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572}
6573
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006574/*
6575 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6576 * parsing sessions.
6577 */
6578void cfg_register_keywords(struct cfg_kw_list *kwl)
6579{
6580 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6581}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006583/*
6584 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6585 */
6586void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6587{
6588 LIST_DEL(&kwl->list);
6589 LIST_INIT(&kwl->list);
6590}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006591
6592/*
6593 * Local variables:
6594 * c-indent-level: 8
6595 * c-basic-offset: 8
6596 * End:
6597 */